normalize static method
Produces a normalized version of a full URL string by applying various standardizations:
- Converts scheme and host to lowercase
- Removes default ports (80 for HTTP, 443 for HTTPS)
- Resolves path segments (
.
and..
) - Reduces multiple slashes
- Removes trailing slashes for non-root paths
- Sorts and re-encodes query parameters
- Re-encodes fragment
- Preserves user info
Example:
final url = 'HTTP://Example.com:80/users?id=2&name=John';
final normalized = UriTemplate.normalize(url);
print(normalized); // http://example.com/users?id=2&name=John
Implementation
static String normalize(String url) {
Uri uri = Uri.parse(url);
// Scheme normalization: lowercase
String normalizedScheme = uri.scheme.toLowerCase();
// Host normalization: lowercase and remove trailing dot
String normalizedHost = uri.host.toLowerCase();
if (normalizedHost.isNotEmpty && normalizedHost.endsWith('.')) {
normalizedHost = normalizedHost.substring(0, normalizedHost.length - 1);
}
// Port normalization: remove default ports
int? normalizedPort = uri.port;
if ((normalizedScheme == 'http' && normalizedPort == 80) ||
(normalizedScheme == 'https' && normalizedPort == 443)) {
normalizedPort = null; // Indicate default port, so it's not included in the URI string
}
// Path normalization: resolve . and .., reduce multiple slashes, remove trailing slash for non-root
String normalizedPath = uri.path;
if (normalizedPath.isEmpty) {
normalizedPath = '/'; // Empty path becomes root path
} else {
// Use Uri.parse().normalizePath() to resolve . and .. and handle multiple slashes.
// This also handles percent-encoding for path segments.
normalizedPath = normalizePath(normalizedPath);
// Remove trailing slash if it's not the root path
if (normalizedPath.length > 1 && normalizedPath.endsWith('/')) {
normalizedPath = normalizedPath.substring(0, normalizedPath.length - 1);
}
}
// Query normalization: sort parameters by key, then by value, and re-encode
Map<String, List<String>> queryParams = uri.queryParametersAll;
List<String> sortedKeys = queryParams.keys.toList()..sort();
List<String> normalizedQuerySegments = [];
for (String key in sortedKeys) {
List<String> values = List.from(queryParams[key]!)..sort(); // Sort values for each key
String encodedKey = Uri.encodeQueryComponent(key);
for (String value in values) {
String encodedValue = Uri.encodeQueryComponent(value);
normalizedQuerySegments.add('$encodedKey=$encodedValue');
}
}
String? normalizedQuery = normalizedQuerySegments.isEmpty ? null : normalizedQuerySegments.join('&');
// Fragment normalization: re-encode
String? normalizedFragment = uri.fragment.isEmpty ? null : Uri.encodeComponent(uri.fragment);
// Reconstruct the URI
Uri resultUri = Uri(
scheme: normalizedScheme,
userInfo: uri.userInfo.isEmpty ? null : uri.userInfo, // Preserve user info if present
host: normalizedHost,
port: normalizedPort,
path: normalizedPath,
query: normalizedQuery,
fragment: normalizedFragment,
);
return resultUri.toString();
}