v10
This commit is contained in:
158
test/parser/path_utils.dart
Normal file
158
test/parser/path_utils.dart
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
final RegExp _parameterRegExp = RegExp(r':(\w+)(\((?:\\.|[^\\()])+\))?');
|
||||
|
||||
/// Converts a [pattern] such as `/user/:id` into [RegExp].
|
||||
///
|
||||
/// The path parameters can be specified by prefixing them with `:`. The
|
||||
/// `parameters` are used for storing path parameter names.
|
||||
///
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// `pattern` = `/user/:id/book/:bookId`
|
||||
///
|
||||
/// The `parameters` would contain `['id', 'bookId']` as a result of calling
|
||||
/// this method.
|
||||
///
|
||||
/// To extract the path parameter values from a [RegExpMatch], pass the
|
||||
/// [RegExpMatch] into [extractPathParameters] with the `parameters` that are
|
||||
/// used for generating the [RegExp].
|
||||
RegExp patternToRegExp(String pattern, List<String> parameters) {
|
||||
final StringBuffer buffer = StringBuffer('^');
|
||||
int start = 0;
|
||||
for (final RegExpMatch match in _parameterRegExp.allMatches(pattern)) {
|
||||
if (match.start > start) {
|
||||
buffer.write(RegExp.escape(pattern.substring(start, match.start)));
|
||||
}
|
||||
final String name = match[1]!;
|
||||
final String? optionalPattern = match[2];
|
||||
final String regex = optionalPattern != null
|
||||
? _escapeGroup(optionalPattern, name)
|
||||
: '(?<$name>[^/]+)';
|
||||
buffer.write(regex);
|
||||
parameters.add(name);
|
||||
start = match.end;
|
||||
}
|
||||
|
||||
if (start < pattern.length) {
|
||||
buffer.write(RegExp.escape(pattern.substring(start)));
|
||||
}
|
||||
|
||||
if (!pattern.endsWith('/')) {
|
||||
buffer.write(r'(?=/|$)');
|
||||
}
|
||||
return RegExp(buffer.toString(), caseSensitive: false);
|
||||
}
|
||||
|
||||
String _escapeGroup(String group, [String? name]) {
|
||||
final String escapedGroup = group.replaceFirstMapped(
|
||||
RegExp(r'[:=!]'), (Match match) => '\\${match[0]}');
|
||||
if (name != null) {
|
||||
return '(?<$name>$escapedGroup)';
|
||||
}
|
||||
return escapedGroup;
|
||||
}
|
||||
|
||||
/// Reconstructs the full path from a [pattern] and path parameters.
|
||||
///
|
||||
/// This is useful for restoring the original path from a [RegExpMatch].
|
||||
///
|
||||
/// For example, A path matched a [RegExp] returned from [patternToRegExp] and
|
||||
/// produced a [RegExpMatch]. To reconstruct the path from the match, one
|
||||
/// can follow these steps:
|
||||
///
|
||||
/// 1. Get the `pathParameters` by calling [extractPathParameters] with the
|
||||
/// [RegExpMatch] and the parameters used for generating the [RegExp].
|
||||
/// 2. Call [patternToPath] with the `pathParameters` from the first step and
|
||||
/// the original `pattern` used for generating the [RegExp].
|
||||
String patternToPath(String pattern, Map<String, String> pathParameters) {
|
||||
final StringBuffer buffer = StringBuffer();
|
||||
int start = 0;
|
||||
for (final RegExpMatch match in _parameterRegExp.allMatches(pattern)) {
|
||||
if (match.start > start) {
|
||||
buffer.write(pattern.substring(start, match.start));
|
||||
}
|
||||
final String name = match[1]!;
|
||||
buffer.write(pathParameters[name]);
|
||||
start = match.end;
|
||||
}
|
||||
|
||||
if (start < pattern.length) {
|
||||
buffer.write(pattern.substring(start));
|
||||
}
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
/// Extracts arguments from the `match` and maps them by parameter name.
|
||||
///
|
||||
/// The [parameters] should originate from the call to [patternToRegExp] that
|
||||
/// creates the [RegExp].
|
||||
Map<String, String> extractPathParameters(
|
||||
List<String> parameters, RegExpMatch match) {
|
||||
return <String, String>{
|
||||
for (int i = 0; i < parameters.length; ++i)
|
||||
parameters[i]: match.namedGroup(parameters[i])!
|
||||
};
|
||||
}
|
||||
|
||||
/// Concatenates two paths.
|
||||
///
|
||||
/// e.g: pathA = /a, pathB = c/d, concatenatePaths(pathA, pathB) = /a/c/d.
|
||||
String concatenatePaths(String parentPath, String childPath) {
|
||||
// at the root, just return the path
|
||||
if (parentPath.isEmpty) {
|
||||
assert(childPath.startsWith('/'));
|
||||
assert(childPath == '/' || !childPath.endsWith('/'));
|
||||
return childPath;
|
||||
}
|
||||
|
||||
// not at the root, so append the parent path
|
||||
assert(childPath.isNotEmpty);
|
||||
assert(!childPath.startsWith('/'));
|
||||
assert(!childPath.endsWith('/'));
|
||||
return '${parentPath == '/' ? '' : parentPath}/$childPath';
|
||||
}
|
||||
|
||||
/// Normalizes the location string.
|
||||
String canonicalUri(String loc) {
|
||||
String canon = Uri.parse(loc).toString();
|
||||
canon = canon.endsWith('?') ? canon.substring(0, canon.length - 1) : canon;
|
||||
|
||||
// remove trailing slash except for when you shouldn't, e.g.
|
||||
// /profile/ => /profile
|
||||
// / => /
|
||||
// /login?from=/ => login?from=/
|
||||
canon = canon.endsWith('/') && canon != '/' && !canon.contains('?')
|
||||
? canon.substring(0, canon.length - 1)
|
||||
: canon;
|
||||
|
||||
// /login/?from=/ => /login?from=/
|
||||
// /?from=/ => /?from=/
|
||||
canon = canon.replaceFirst('/?', '?', 1);
|
||||
|
||||
return canon;
|
||||
}
|
||||
|
||||
/// Builds an absolute path for the provided route.
|
||||
// String? fullPathForRoute(
|
||||
// RouteBase targetRoute, String parentFullpath, List<RouteBase> routes) {
|
||||
// for (final RouteBase route in routes) {
|
||||
// final String fullPath = (route is GoRoute)
|
||||
// ? concatenatePaths(parentFullpath, route.path)
|
||||
// : parentFullpath;
|
||||
//
|
||||
// if (route == targetRoute) {
|
||||
// return fullPath;
|
||||
// } else {
|
||||
// final String? subRoutePath =
|
||||
// fullPathForRoute(targetRoute, fullPath, route.routes);
|
||||
// if (subRoutePath != null) {
|
||||
// return subRoutePath;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
107
test/parser/uri.dart
Normal file
107
test/parser/uri.dart
Normal file
@@ -0,0 +1,107 @@
|
||||
import 'path_utils.dart';
|
||||
|
||||
void main() {
|
||||
String pattern = '/user/:id/book/:bookId';
|
||||
String path = '/user/001/book/card';
|
||||
|
||||
parserPath();
|
||||
// List<String> params = [];
|
||||
// RegExp regExp = patternToRegExp(pattern,params);
|
||||
//
|
||||
//
|
||||
// bool data = regExp.hasMatch(path);
|
||||
// List<RegExpMatch> matchs = regExp.allMatches(path).toList();
|
||||
// Map<String,String?> pathParams = {};
|
||||
// if(matchs.isNotEmpty){
|
||||
//
|
||||
// for(int i=0;i<params.length;i++){
|
||||
// String? value = matchs.first.namedGroup(params[i]);
|
||||
// pathParams[params[i]] = value;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// print(pathParams);
|
||||
// print(regExp.pattern);
|
||||
//
|
||||
// // match.forEach((element) {
|
||||
// // print(element.namedGroup('id'));
|
||||
// // });
|
||||
// // regExp
|
||||
// print(params);
|
||||
// String ret = patternToPath(pattern, {
|
||||
// 'id':'0',
|
||||
// 'bookId':'card',
|
||||
// });
|
||||
// print(regExp);
|
||||
// print(ret);
|
||||
}
|
||||
|
||||
void parserPath() {
|
||||
String template = '/user/:id/book/:bookId';
|
||||
String path = '/user/001/book/card';
|
||||
List<String> keys = [];
|
||||
RegExp regExp = patternToRegExp(template,keys);
|
||||
Map<String, String?> pathParams = {};
|
||||
RegExpMatch? match = regExp.firstMatch(path);
|
||||
|
||||
if (match != null) {
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
String? value = match.namedGroup(keys[i]);
|
||||
pathParams[keys[i]] = value;
|
||||
}
|
||||
}
|
||||
print(pathParams);
|
||||
}
|
||||
|
||||
|
||||
final RegExp _parameterRegExp = RegExp(r':(\w+)(\((?:\\.|[^\\()])+\))?');
|
||||
|
||||
RegExp patternToRegExp(String pattern, List<String> parameters) {
|
||||
final StringBuffer buffer = StringBuffer('^');
|
||||
int start = 0;
|
||||
for (final RegExpMatch match in _parameterRegExp.allMatches(pattern)) {
|
||||
if (match.start > start) {
|
||||
buffer.write(RegExp.escape(pattern.substring(start, match.start)));
|
||||
}
|
||||
final String name = match[1]!;
|
||||
final String? optionalPattern = match[2];
|
||||
final String regex = optionalPattern != null
|
||||
? _escapeGroup(optionalPattern, name)
|
||||
: '(?<$name>[^/]+)';
|
||||
buffer.write(regex);
|
||||
parameters.add(name);
|
||||
start = match.end;
|
||||
}
|
||||
|
||||
if (start < pattern.length) {
|
||||
buffer.write(RegExp.escape(pattern.substring(start)));
|
||||
}
|
||||
|
||||
if (!pattern.endsWith('/')) {
|
||||
buffer.write(r'(?=/|$)');
|
||||
}
|
||||
return RegExp(buffer.toString(), caseSensitive: false);
|
||||
}
|
||||
|
||||
String _escapeGroup(String group, [String? name]) {
|
||||
final String escapedGroup = group.replaceFirstMapped(
|
||||
RegExp(r'[:=!]'), (Match match) => '\\${match[0]}');
|
||||
if (name != null) {
|
||||
return '(?<$name>$escapedGroup)';
|
||||
}
|
||||
return escapedGroup;
|
||||
}
|
||||
|
||||
void parser() {
|
||||
String path =
|
||||
'http://user:pwd@toly1994.com:8080/path1/path2?key1=value1&key2=value2#fragment';
|
||||
Uri? uri = Uri.tryParse(path);
|
||||
if (uri == null) return;
|
||||
print(uri.scheme); // http
|
||||
print(uri.userInfo); // user:pwd
|
||||
print(uri.host); // toly1994.com
|
||||
print(uri.port); // 8080
|
||||
print(uri.path); // /path1/path2
|
||||
print(uri.query); // key1=value1&key2=value2
|
||||
print(uri.fragment); // fragment
|
||||
}
|
||||
Reference in New Issue
Block a user