Appearance
Uri abstract interface
abstract interface class UriA parsed URI, such as a URL.
To create a URI with specific components, use Uri.new:
dart
var httpsUri = Uri(
scheme: 'https',
host: 'dart.dev',
path: 'language/built-in-types',
fragment: 'numbers');
print(httpsUri); // https://dart.dev/language/built-in-types#numbers
httpsUri = Uri(
scheme: 'https',
host: 'example.com',
path: '/page/',
queryParameters: {'search': 'blue', 'limit': '10'});
print(httpsUri); // https://example.com/page/?search=blue&limit=10
final mailtoUri = Uri(
scheme: 'mailto',
path: 'John.Doe@example.com',
queryParameters: {'subject': 'Example'});
print(mailtoUri); // mailto:John.Doe@example.com?subject=ExampleHTTP and HTTPS URI
To create a URI with https scheme, use Uri.https or Uri.http:
dart
final httpsUri = Uri.https('example.com', 'api/fetch', {'limit': '10'});
print(httpsUri); // https://example.com/api/fetch?limit=10File URI
To create a URI from file path, use Uri.file:
dart
final fileUriUnix =
Uri.file(r'/home/myself/images/image.png', windows: false);
print(fileUriUnix); // file:///home/myself/images/image.png
final fileUriWindows =
Uri.file(r'C:\Users\myself\Documents\image.png', windows: true);
print(fileUriWindows); // file:///C:/Users/myself/Documents/image.pngIf the URI is not a file URI, calling this throws UnsupportedError.
Directory URI
Like Uri.file except that a non-empty URI path ends in a slash.
dart
final fileDirectory =
Uri.directory('/home/myself/data/image', windows: false);
print(fileDirectory); // file:///home/myself/data/image/
final fileDirectoryWindows = Uri.directory('/data/images', windows: true);
print(fileDirectoryWindows); // file:///data/images/URI from string
To create a URI from string, use Uri.parse or Uri.tryParse:
dart
final uri = Uri.parse(
'https://dart.dev/libraries/dart-core#utility-classes');
print(uri); // https://dart.dev
print(uri.isScheme('https')); // true
print(uri.origin); // https://dart.dev
print(uri.host); // dart.dev
print(uri.authority); // dart.dev
print(uri.port); // 443
print(uri.path); // libraries/dart-core
print(uri.pathSegments); // [libraries, dart-core]
print(uri.fragment); // utility-classes
print(uri.hasQuery); // false
print(uri.data); // nullSee also:
Constructors
Uri() factory
factory Uri({
String? scheme,
String? userInfo,
String? host,
int? port,
String? path,
Iterable<String>? pathSegments,
String? query,
Map<String, dynamic>? queryParameters,
String? fragment,
})Creates a new URI from its components.
Each component is set through a named argument. Any number of components can be provided. The path and query components can be set using either of two different named arguments.
The scheme component is set through scheme. The scheme is normalized to all lowercase letters. If the scheme is omitted or empty, the URI will not have a scheme part.
The user info part of the authority component is set through userInfo. It defaults to the empty string, which will be omitted from the string representation of the URI.
The host part of the authority component is set through host. The host can either be a hostname, an IPv4 address or an IPv6 address, contained in '[' and ']'. If the host contains a ':' character, the '[' and ']' are added if not already provided. The host is normalized to all lowercase letters.
The port part of the authority component is set through port. If port is omitted or null, it implies the default port for the URI's scheme, and is equivalent to passing that port explicitly. The recognized schemes, and their default ports, are "http" (80) and "https" (443). All other schemes are considered as having zero as the default port.
If any of userInfo, host or port are provided, the URI has an authority according to hasAuthority.
The path component is set through either path or pathSegments. When path is used, it should be a valid URI path, but invalid characters, except the general delimiters '😕@[]?#', will be escaped if necessary. A backslash, \, will be converted to a slash /. When pathSegments is used, each of the provided segments is first percent-encoded and then joined using the forward slash separator.
The percent-encoding of the path segments encodes all characters except for the unreserved characters and the following list of characters: !$&'()*+,;=:@. If the other components necessitate an absolute path, a leading slash / is prepended if not already there.
The query component is set through either query or queryParameters. When query is used, the provided string should be a valid URI query, but invalid characters, other than general delimiters, will be escaped if necessary. When queryParameters is used, the query is built from the provided map. Each key and value in the map is percent-encoded and joined using equal and ampersand characters. A value in the map must be either null, a string, or an Iterable of strings. An iterable corresponds to multiple values for the same key, and an empty iterable or null corresponds to no value for the key.
The percent-encoding of the keys and values encodes all characters except for the unreserved characters, and replaces spaces with +. If query is the empty string, it is equivalent to omitting it. To have an actual empty query part, use an empty map for queryParameters.
If both query and queryParameters are omitted or null, the URI has no query part.
The fragment component is set through fragment. It should be a valid URI fragment, but invalid characters other than general delimiters are escaped if necessary. If fragment is omitted or null, the URI has no fragment part.
Example:
dart
final httpsUri = Uri(
scheme: 'https',
host: 'dart.dev',
path: 'language/built-in-types',
fragment: 'numbers');
print(httpsUri); // https://dart.dev/language/built-in-types#numbers
final mailtoUri = Uri(
scheme: 'mailto',
path: 'John.Doe@example.com',
queryParameters: {'subject': 'Example'});
print(mailtoUri); // mailto:John.Doe@example.com?subject=ExampleImplementation
dart
factory Uri({
String? scheme,
String? userInfo,
String? host,
int? port,
String? path,
Iterable<String>? pathSegments,
String? query,
Map<String, dynamic /*String?|Iterable<String>*/>? queryParameters,
String? fragment,
}) = _Uri;Uri.dataFromBytes() factory
factory Uri.dataFromBytes(
List<int> bytes, {
String mimeType = "application/octet-stream",
Map<String, String>? parameters,
bool percentEncoded = false,
})Creates a data: URI containing an encoding of bytes.
Defaults to Base64 encoding the bytes, but if percentEncoded is true, the bytes will instead be percent encoded (any non-ASCII or non-valid-ASCII-character byte is replaced by a percent encoding).
To read the bytes back, use UriData.contentAsBytes.
It defaults to having the mime-type application/octet-stream. The mimeType and parameters are added to the created URI. If any of these contain characters that are not allowed in the data URI, the character is percent-escaped. If the character is non-ASCII, it is first UTF-8 encoded and then the bytes are percent encoded.
Example:
dart
final uri = Uri.dataFromBytes([68, 97, 114, 116]);
print(uri); // data:application/octet-stream;base64,RGFydA==Implementation
dart
factory Uri.dataFromBytes(
List<int> bytes, {
String mimeType = "application/octet-stream",
Map<String, String>? parameters,
bool percentEncoded = false,
}) {
UriData data = UriData.fromBytes(
bytes,
mimeType: mimeType,
parameters: parameters,
percentEncoded: percentEncoded,
);
return data.uri;
}Uri.dataFromString() factory
factory Uri.dataFromString(
String content, {
String? mimeType,
Encoding? encoding,
Map<String, String>? parameters,
bool base64 = false,
})Creates a data: URI containing the content string.
Converts the content to bytes using encoding or the charset specified in parameters (defaulting to US-ASCII if not specified or unrecognized), then encodes the bytes into the resulting data URI.
Defaults to encoding using percent-encoding (any non-ASCII or non-URI-valid bytes is replaced by a percent encoding). If base64 is true, the bytes are instead encoded using base64.
If encoding is not provided and parameters has a charset entry, that name is looked up using Encoding.getByName, and if the lookup returns an encoding, that encoding is used to convert content to bytes. If providing both an encoding and a charset in parameters, they should agree, otherwise decoding won't be able to use the charset parameter to determine the encoding.
If mimeType and/or parameters are supplied, they are added to the created URI. If any of these contain characters that are not allowed in the data URI, the character is percent-escaped. If the character is non-ASCII, it is first UTF-8 encoded and then the bytes are percent encoded. An omitted mimeType in a data URI means text/plain, just as an omitted charset parameter defaults to meaning US-ASCII.
To read the content back, use UriData.contentAsString.
Example:
dart
final uri = Uri.dataFromString(
'example content',
mimeType: 'text/plain',
parameters: <String, String>{'search': 'file', 'max': '10'},
);
print(uri); // data:;search=name;max=10,example%20contentImplementation
dart
factory Uri.dataFromString(
String content, {
String? mimeType,
Encoding? encoding,
Map<String, String>? parameters,
bool base64 = false,
}) {
UriData data = UriData.fromString(
content,
mimeType: mimeType,
encoding: encoding,
parameters: parameters,
base64: base64,
);
return data.uri;
}Uri.directory() factory
Like Uri.file except that a non-empty URI path ends in a slash.
If path is not empty, and it doesn't end in a directory separator, then a slash is added to the returned URI's path. In all other cases, the result is the same as returned by Uri.file.
Example:
dart
final fileDirectory = Uri.directory('data/images', windows: false);
print(fileDirectory); // data/images/
final fileDirectoryWindows =
Uri.directory(r'C:\data\images', windows: true);
print(fileDirectoryWindows); // file:///C:/data/images/Implementation
dart
factory Uri.directory(String path, {bool? windows}) = _Uri.directory;Uri.file() factory
Creates a new file URI from an absolute or relative file path.
The file path is passed in path.
This path is interpreted using either Windows or non-Windows semantics.
With non-Windows semantics, the slash (/) is used to separate path segments in the input path.
With Windows semantics, backslash (\) and forward-slash (/) are used to separate path segments in the input path, except if the path starts with \\?\ in which case only backslash (\) separates path segments in path.
If the path starts with a path separator, an absolute URI (with the file scheme and an empty authority) is created. Otherwise a relative URI reference with no scheme or authority is created. One exception to this rule is that when Windows semantics is used and the path starts with a drive letter followed by a colon ("😊 and a path separator, then an absolute URI is created.
The default for whether to use Windows or non-Windows semantics is determined from the platform Dart is running on. When running in the standalone VM, this is detected by the VM based on the operating system. When running in a browser, non-Windows semantics is always used.
To override the automatic detection of which semantics to use pass a value for windows. Passing true will use Windows semantics and passing false will use non-Windows semantics.
Examples using non-Windows semantics:
dart
// xxx/yyy
Uri.file('xxx/yyy', windows: false);
// xxx/yyy/
Uri.file('xxx/yyy/', windows: false);
// file:///xxx/yyy
Uri.file('/xxx/yyy', windows: false);
// file:///xxx/yyy/
Uri.file('/xxx/yyy/', windows: false);
// C%3A
Uri.file('C:', windows: false);Examples using Windows semantics:
dart
// xxx/yyy
Uri.file(r'xxx\yyy', windows: true);
// xxx/yyy/
Uri.file(r'xxx\yyy\', windows: true);
file:///xxx/yyy
Uri.file(r'\xxx\yyy', windows: true);
file:///xxx/yyy/
Uri.file(r'\xxx\yyy/', windows: true);
// file:///C:/xxx/yyy
Uri.file(r'C:\xxx\yyy', windows: true);
// This throws an error. A path with a drive letter, but no following
// path, is not allowed.
Uri.file(r'C:', windows: true);
// This throws an error. A path with a drive letter is not absolute.
Uri.file(r'C:xxx\yyy', windows: true);
// file://server/share/file
Uri.file(r'\\server\share\file', windows: true);If the path passed is not a valid file path, an error is thrown.
Implementation
dart
factory Uri.file(String path, {bool? windows}) = _Uri.file;Uri.http() factory
factory Uri.http(
String authority, [
String unencodedPath,
Map<String, dynamic>? queryParameters,
])Creates a new http URI from authority, path and query.
Example:
dart
var uri = Uri.http('example.org', '/path', { 'q' : 'dart' });
print(uri); // http://example.org/path?q=dart
uri = Uri.http('user:password@localhost:8080', '');
print(uri); // http://user:password@localhost:8080
uri = Uri.http('example.org', 'a b');
print(uri); // http://example.org/a%20b
uri = Uri.http('example.org', '/a%2F');
print(uri); // http://example.org/a%252FThe scheme is always set to http.
The userInfo, host and port components are set from the authority argument. If authority is null or empty, the created Uri has no authority, and isn't directly usable as an HTTP URL, which must have a non-empty host.
The path component is set from the unencodedPath argument. The path passed must not be encoded as this constructor encodes the path. Only / is recognized as path separator. If omitted, the path defaults to being empty.
The query component is set from the optional queryParameters argument.
Implementation
dart
factory Uri.http(
String authority, [
String unencodedPath,
Map<String, dynamic /*String?|Iterable<String>*/>? queryParameters,
]) = _Uri.http;Uri.https() factory
factory Uri.https(
String authority, [
String unencodedPath,
Map<String, dynamic>? queryParameters,
])Creates a new https URI from authority, path and query.
This constructor is the same as Uri.http except for the scheme which is set to https.
Example:
dart
var uri = Uri.https('example.org', '/path', {'q': 'dart'});
print(uri); // https://example.org/path?q=dart
uri = Uri.https('user:password@localhost:8080', '');
print(uri); // https://user:password@localhost:8080
uri = Uri.https('example.org', 'a b');
print(uri); // https://example.org/a%20b
uri = Uri.https('example.org', '/a%2F');
print(uri); // https://example.org/a%252FImplementation
dart
factory Uri.https(
String authority, [
String unencodedPath,
Map<String, dynamic>? queryParameters,
]) = _Uri.https;Properties
authority no setter
String get authorityThe authority component.
The authority is formatted from the userInfo, host and port parts.
The value is the empty string if there is no authority component.
Implementation
dart
String get authority;data no setter
UriData? get dataAccess the structure of a data: URI.
Returns a UriData object for data: URIs and null for all other URIs. The UriData object can be used to access the media type and data of a data: URI.
Implementation
dart
UriData? get data;fragment no setter
String get fragmentThe fragment identifier component.
The value is the empty string if there is no fragment identifier component.
Implementation
dart
String get fragment;hasAbsolutePath no setter
bool get hasAbsolutePathWhether the URI has an absolute path (starting with '/').
Implementation
dart
bool get hasAbsolutePath;hasAuthority no setter
bool get hasAuthorityWhether the URI has an authority component.
Implementation
dart
bool get hasAuthority;hasEmptyPath no setter
bool get hasEmptyPathWhether the URI has an empty path.
Implementation
dart
bool get hasEmptyPath;hasFragment no setter
bool get hasFragmentWhether the URI has a fragment part.
Implementation
dart
bool get hasFragment;hashCode no setter override
int get hashCodeReturns a hash code computed as toString().hashCode.
This guarantees that URIs with the same normalized string representation have the same hash code.
Implementation
dart
int get hashCode;hasPort no setter
bool get hasPortWhether the URI has an explicit port.
If the port number is the default port number (zero for unrecognized schemes, with http (80) and https (443) being recognized), then the port is made implicit and omitted from the URI.
Implementation
dart
bool get hasPort;hasQuery no setter
bool get hasQueryWhether the URI has a query part.
Implementation
dart
bool get hasQuery;hasScheme no setter
bool get hasSchemeWhether the URI has a scheme component.
Implementation
dart
bool get hasScheme => scheme.isNotEmpty;host no setter
String get hostThe host part of the authority component.
The value is the empty string if there is no authority component and hence no host.
If the host is an IP version 6 address, the surrounding [ and ] is removed.
The host string is case-insensitive. The returned host name is canonicalized to lower-case with upper-case percent-escapes.
Implementation
dart
String get host;isAbsolute no setter
bool get isAbsoluteWhether the URI is absolute.
A URI is an absolute URI in the sense of RFC 3986 if it has a scheme and no fragment.
Implementation
dart
bool get isAbsolute;origin no setter
String get originReturns the origin of the URI in the form scheme://host:port for the schemes http and https.
It is an error if the scheme is not "http" or "https", or if the host name is missing or empty.
See: https://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
Implementation
dart
String get origin;path no setter
String get pathThe path component.
The path is the actual substring of the URI representing the path, and it is encoded where necessary. To get direct access to the decoded path, use pathSegments.
The path value is the empty string if there is no path component.
Implementation
dart
String get path;pathSegments no setter
The URI path split into its segments.
Each of the segments in the list has been decoded. If the path is empty, the empty list will be returned. A leading slash / does not affect the segments returned.
The list is unmodifiable and will throw UnsupportedError on any calls that would mutate it.
Implementation
dart
List<String> get pathSegments;port no setter
int get portThe port part of the authority component.
The value is the default port if there is no port number in the authority component. That's 80 for http, 443 for https, and 0 for everything else.
Implementation
dart
int get port;query no setter
String get queryThe query component.
The value is the actual substring of the URI representing the query part, and it is encoded where necessary. To get direct access to the decoded query, use queryParameters.
The value is the empty string if there is no query component.
Implementation
dart
String get query;queryParameters no setter
The URI query split into a map according to the rules specified for FORM post in the HTML 4.01 specification section 17.13.4.
Each key and value in the resulting map has been decoded. If there is no query, the empty map is returned.
Keys in the query string that have no value are mapped to the empty string. If a key occurs more than once in the query string, it is mapped to an arbitrary choice of possible value. The queryParametersAll getter can provide a map that maps keys to all of their values.
Example:
dart
final uri =
Uri.parse('https://example.com/api/fetch?limit=10,20,30&max=100');
print(jsonEncode(uri.queryParameters));
// {"limit":"10,20,30","max":"100"}The map is unmodifiable.
Implementation
dart
Map<String, String> get queryParameters;queryParametersAll no setter
Returns the URI query split into a map according to the rules specified for FORM post in the HTML 4.01 specification section 17.13.4.
Each key and value in the resulting map has been decoded. If there is no query, the map is empty.
Keys are mapped to lists of their values. If a key occurs only once, its value is a singleton list. If a key occurs with no value, the empty string is used as the value for that occurrence.
Example:
dart
final uri =
Uri.parse('https://example.com/api/fetch?limit=10&limit=20&limit=30&max=100');
print(jsonEncode(uri.queryParametersAll)); // {"limit":["10","20","30"],"max":["100"]}The map and the lists it contains are unmodifiable.
Implementation
dart
Map<String, List<String>> get queryParametersAll;runtimeType no setter inherited
Type get runtimeTypeA representation of the runtime type of the object.
Inherited from Object.
Implementation
dart
external Type get runtimeType;scheme no setter
String get schemeThe scheme component of the URI.
The value is the empty string if there is no scheme component.
A URI scheme is case insensitive. The returned scheme is canonicalized to lowercase letters.
Implementation
dart
String get scheme;userInfo no setter
String get userInfoThe user info part of the authority component.
The value is the empty string if there is no user info in the authority component.
Implementation
dart
String get userInfo;Methods
isScheme()
Whether the scheme of this Uri is scheme.
The scheme should be the same as the one returned by Uri.scheme, but doesn't have to be case-normalized to lower-case characters.
Example:
dart
var uri = Uri.parse('http://example.com');
print(uri.isScheme('HTTP')); // true
final uriNoScheme = Uri(host: 'example.com');
print(uriNoScheme.isScheme('HTTP')); // falseAn empty scheme string matches a URI with no scheme (one where hasScheme returns false).
Implementation
dart
bool isScheme(String scheme);normalizePath()
Uri normalizePath()Returns a URI where the path has been normalized.
A normalized path does not contain . segments or non-leading .. segments. Only a relative path with no scheme or authority may contain leading .. segments; a path that starts with / will also drop any leading .. segments.
This uses the same normalization strategy as Uri().resolve(this).
Does not change any part of the URI except the path.
The default implementation of Uri always normalizes paths, so calling this function has no effect.
Implementation
dart
Uri normalizePath();noSuchMethod() inherited
dynamic noSuchMethod(Invocation invocation)Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dart
dynamic object = 1;
object.add(42); // Statically allowed, run-time errorThis invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
dart
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.
If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Inherited from Object.
Implementation
dart
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);removeFragment()
Uri removeFragment()Creates a Uri that differs from this only in not having a fragment.
If this Uri does not have a fragment, it is itself returned.
Example:
dart
final uri =
Uri.parse('https://example.org:8080/foo/bar#frag').removeFragment();
print(uri); // https://example.org:8080/foo/barImplementation
dart
Uri removeFragment();replace()
Uri replace({
String? scheme,
String? userInfo,
String? host,
int? port,
String? path,
Iterable<String>? pathSegments,
String? query,
Map<String, dynamic>? queryParameters,
String? fragment,
})Creates a new Uri based on this one, but with some parts replaced.
This method takes the same parameters as the Uri constructor, and they have the same meaning.
At most one of path and pathSegments must be provided. Likewise, at most one of query and queryParameters must be provided.
Each part that is not provided will default to the corresponding value from this Uri instead.
This method is different from Uri.resolve, which overrides in a hierarchical manner, and can instead replace each part of a Uri individually.
Example:
dart
final uri1 = Uri.parse(
'https://dart.dev/libraries/dart-core#utility-classes');
final uri2 = uri1.replace(
scheme: 'https',
path: 'libraries/dart-core',
fragment: 'uris');
print(uri2); // https://dart.dev/libraries/dart-core#urisThis method acts similarly to using the Uri constructor with some of the arguments taken from this Uri. Example:
dart
final Uri uri3 = Uri(
scheme: 'https',
userInfo: uri1.userInfo,
host: uri1.host,
port: uri2.port,
path: 'language/built-in-types',
query: uri1.query,
fragment: null);
print(uri3); // https://dart.dev/language/built-in-typesUsing this method can be seen as shorthand for the Uri constructor call above, but may also be slightly faster because the parts taken from this Uri need not be checked for validity again.
Implementation
dart
Uri replace({
String? scheme,
String? userInfo,
String? host,
int? port,
String? path,
Iterable<String>? pathSegments,
String? query,
Map<String, dynamic /*String?|Iterable<String>*/>? queryParameters,
String? fragment,
});resolve()
Resolve reference as an URI relative to this.
First turn reference into a URI using Uri.parse. Then resolve the resulting URI relative to this.
Returns the resolved URI.
See resolveUri for details.
Implementation
dart
Uri resolve(String reference);resolveUri()
Resolve reference as a URI relative to this.
Returns the resolved URI.
The algorithm "Transform Reference" for resolving a reference is described in RFC-3986 Section 5.
Updated to handle the case where the base URI is just a relative path - that is: when it has no scheme and no authority and the path does not start with a slash. In that case, the paths are combined without removing leading "..", and an empty path is not converted to "/".
Implementation
dart
Uri resolveUri(Uri reference);toFilePath()
Creates a file path from a file URI.
The returned path has either Windows or non-Windows semantics.
For non-Windows semantics, the slash ("/") is used to separate path segments.
For Windows semantics, the backslash ("") separator is used to separate path segments.
If the URI is absolute, the path starts with a path separator unless Windows semantics is used and the first path segment is a drive letter. When Windows semantics is used, a host component in the uri in interpreted as a file server and a UNC path is returned.
The default for whether to use Windows or non-Windows semantics is determined from the platform Dart is running on. When running in the standalone VM, this is detected by the VM based on the operating system. When running in a browser, non-Windows semantics is always used.
To override the automatic detection of which semantics to use pass a value for windows. Passing true will use Windows semantics and passing false will use non-Windows semantics.
If the URI ends with a slash (i.e. the last path component is empty), the returned file path will also end with a slash.
With Windows semantics, URIs starting with a drive letter cannot be relative to the current drive on the designated drive. That is, for the URI file:///c:abc calling toFilePath will throw as a path segment cannot contain colon on Windows.
Examples using non-Windows semantics (resulting of calling toFilePath in comment):
dart
Uri.parse("xxx/yyy"); // xxx/yyy
Uri.parse("xxx/yyy/"); // xxx/yyy/
Uri.parse("file:///xxx/yyy"); // /xxx/yyy
Uri.parse("file:///xxx/yyy/"); // /xxx/yyy/
Uri.parse("file:///C:"); // /C:
Uri.parse("file:///C:a"); // /C:aExamples using Windows semantics (resulting URI in comment):
dart
Uri.parse("xxx/yyy"); // xxx\yyy
Uri.parse("xxx/yyy/"); // xxx\yyy\
Uri.parse("file:///xxx/yyy"); // \xxx\yyy
Uri.parse("file:///xxx/yyy/"); // \xxx\yyy\
Uri.parse("file:///C:/xxx/yyy"); // C:\xxx\yyy
Uri.parse("file:C:xxx/yyy"); // Throws as a path segment
// cannot contain colon on Windows.
Uri.parse("file://server/share/file"); // \\server\share\fileIf the URI is not a file URI, calling this throws UnsupportedError.
If the URI cannot be converted to a file path, calling this throws UnsupportedError.
Implementation
dart
// TODO(lrn): Deprecate and move functionality to File class or similar.
// The core libraries should not worry about the platform.
String toFilePath({bool? windows});toString() override
String toString()The normalized string representation of the URI.
Implementation
dart
String toString();Operators
operator ==() override
A URI is equal to another URI with the same normalized representation.
Implementation
dart
bool operator ==(Object other);Static Properties
base no setter
Uri get baseThe natural base URI for the current platform.
When running in a browser, this is the current URL of the current page (from window.location.href).
When not running in a browser, this is the file URI referencing the current working directory.
Implementation
dart
external static Uri get base;Static Methods
decodeComponent()
Decodes the percent-encoding in encodedComponent.
Note that decoding a URI component might change its meaning as some of the decoded characters could be characters which are delimiters for a given URI component type. Always split a URI component using the delimiters for the component before decoding the individual parts.
For handling the path and query components, consider using pathSegments and queryParameters to get the separated and decoded component.
Example:
dart
final decoded =
Uri.decodeComponent('http%3A%2F%2Fexample.com%2Fsearch%3DDart');
print(decoded); // http://example.com/search=DartImplementation
dart
static String decodeComponent(String encodedComponent) {
return _Uri._uriDecode(
encodedComponent,
0,
encodedComponent.length,
utf8,
false,
);
}decodeFull()
Decodes the percent-encoding in uri.
Note that decoding a full URI might change its meaning as some of the decoded characters could be reserved characters. In most cases, an encoded URI should be parsed into components using Uri.parse before decoding the separate components.
Example:
dart
final decoded =
Uri.decodeFull('https://example.com/api/query?search=%20dart%20is');
print(decoded); // https://example.com/api/query?search= dart isImplementation
dart
static String decodeFull(String uri) {
return _Uri._uriDecode(uri, 0, uri.length, utf8, false);
}decodeQueryComponent()
Decodes the percent-encoding in encodedComponent, converting pluses to spaces.
It will create a byte-list of the decoded characters, and then use encoding to decode the byte-list to a String. The default encoding is UTF-8.
Implementation
dart
static String decodeQueryComponent(
String encodedComponent, {
Encoding encoding = utf8,
}) {
return _Uri._uriDecode(
encodedComponent,
0,
encodedComponent.length,
encoding,
true,
);
}encodeComponent()
Encode the string component using percent-encoding to make it safe for literal use as a URI component.
All characters except uppercase and lowercase letters, digits and the characters -_.!~*'() are percent-encoded. This is the set of characters specified in RFC 2396 and which is specified for the encodeUriComponent in ECMA-262 version 5.1.
When manually encoding path segments or query components, remember to encode each part separately before building the path or query string.
For encoding the query part consider using encodeQueryComponent.
To avoid the need for explicitly encoding, use the pathSegments and queryParameters optional named arguments when constructing a Uri.
Example:
dart
const request = 'http://example.com/search=Dart';
final encoded = Uri.encodeComponent(request);
print(encoded); // http%3A%2F%2Fexample.com%2Fsearch%3DDartImplementation
dart
static String encodeComponent(String component) {
return _Uri._uriEncode(_unreserved2396Mask, component, utf8, false);
}encodeFull()
Encodes the string uri using percent-encoding to make it safe for literal use as a full URI.
All characters except uppercase and lowercase letters, digits and the characters !#$&'()*+,-./:;=?@_~ are percent-encoded. This is the set of characters specified in ECMA-262 version 5.1 for the encodeURI function.
Example:
dart
final encoded =
Uri.encodeFull('https://example.com/api/query?search= dart is');
print(encoded); // https://example.com/api/query?search=%20dart%20isImplementation
dart
static String encodeFull(String uri) {
return _Uri._uriEncode(_encodeFullMask, uri, utf8, false);
}encodeQueryComponent()
Encodes the string component according to the HTML 4.01 rules for encoding the posting of a HTML form as a query string component.
The component is first encoded to bytes using encoding. The default is to use utf8 encoding, which preserves all the characters that don't need encoding.
Then the resulting bytes are "percent-encoded". This transforms spaces (U+0020) to a plus sign ('+') and all bytes that are not the ASCII decimal digits, letters or one of '-._~' are written as a percent sign '%' followed by the two-digit hexadecimal representation of the byte.
Note that the set of characters which are percent-encoded is a superset of what HTML 4.01 requires, since it refers to RFC 1738 for reserved characters.
When manually encoding query components remember to encode each part separately before building the query string.
To avoid the need for explicitly encoding the query use the queryParameters optional named arguments when constructing a Uri.
See https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.2 for more details.
Implementation
dart
static String encodeQueryComponent(
String component, {
Encoding encoding = utf8,
}) {
return _Uri._uriEncode(_unreservedMask, component, encoding, true);
}parse()
Creates a new Uri object by parsing a URI string.
If start and end are provided, they must specify a valid substring of uri, and only the substring from start to end is parsed as a URI.
If the uri string is not valid as a URI or URI reference, a FormatException is thrown.
Example:
dart
final uri =
Uri.parse('https://example.com/api/fetch?limit=10,20,30&max=100');
print(uri); // https://example.com/api/fetch?limit=10,20,30&max=100
Uri.parse('::Not valid URI::'); // Throws FormatException.Implementation
dart
static Uri parse(String uri, [int start = 0, int? end]) {
// This parsing will not validate percent-encoding, IPv6, etc.
// When done splitting into parts, it will call, e.g., [_makeFragment]
// to do the final parsing.
//
// Important parts of the RFC 3986 used here:
// URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
//
// hier-part = "//" authority path-abempty
// / path-absolute
// / path-rootless
// / path-empty
//
// URI-reference = URI / relative-ref
//
// absolute-URI = scheme ":" hier-part [ "?" query ]
//
// relative-ref = relative-part [ "?" query ] [ "#" fragment ]
//
// relative-part = "//" authority path-abempty
// / path-absolute
// / path-noscheme
// / path-empty
//
// scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
//
// authority = [ userinfo "@" ] host [ ":" port ]
// userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
// host = IP-literal / IPv4address / reg-name
// IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]"
// IPv6addrz = IPv6address "%25" ZoneID
// ZoneID = 1*( unreserved / pct-encoded )
// port = *DIGIT
// reg-name = *( unreserved / pct-encoded / sub-delims )
//
// path = path-abempty ; begins with "/" or is empty
// / path-absolute ; begins with "/" but not "//"
// / path-noscheme ; begins with a non-colon segment
// / path-rootless ; begins with a segment
// / path-empty ; zero characters
//
// path-abempty = *( "/" segment )
// path-absolute = "/" [ segment-nz *( "/" segment ) ]
// path-noscheme = segment-nz-nc *( "/" segment )
// path-rootless = segment-nz *( "/" segment )
// path-empty = 0<pchar>
//
// segment = *pchar
// segment-nz = 1*pchar
// segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
// ; non-zero-length segment without any colon ":"
//
// pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
//
// query = *( pchar / "/" / "?" )
//
// fragment = *( pchar / "/" / "?" )
// Pv6address = 6( h16 ":" ) ls32
// / "::" 5( h16 ":" ) ls32
// / [ h16 ] "::" 4( h16 ":" ) ls32
// / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
// / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
// / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
// / [ *4( h16 ":" ) h16 ] "::" ls32
// / [ *5( h16 ":" ) h16 ] "::" h16
// / [ *6( h16 ":" ) h16 ] "::"
// ls32 = ( h16 ":" h16 ) / IPv4address
// ; least-significant 32 bits of address
// h16 = 1*4HEXDIG
// ; 16 bits of address represented in hexadecimal
end ??= uri.length;
// Special case data:URIs. Ignore case when testing.
if (end >= start + 5) {
int dataDelta = _startsWithData(uri, start);
if (dataDelta == 0) {
// The case is right.
if (start > 0 || end < uri.length) uri = uri.substring(start, end);
return UriData._parse(uri, 5, null).uri;
} else if (dataDelta == 0x20) {
return UriData._parse(uri.substring(start + 5, end), 0, null).uri;
}
// Otherwise the URI doesn't start with "data:" or any case variant of it.
}
// The following index-normalization belongs with the scanning, but is
// easier to do here because we already have extracted variables from the
// indices list.
var indices = List<int>.filled(8, 0, growable: false);
// Set default values for each position.
// The value will either be correct in some cases where it isn't set
// by the scanner, or it is clearly recognizable as an unset value.
indices
..[0] = 0
..[_schemeEndIndex] = start - 1
..[_hostStartIndex] = start - 1
..[_notSimpleIndex] = start - 1
..[_portStartIndex] = start
..[_pathStartIndex] = start
..[_queryStartIndex] = end
..[_fragmentStartIndex] = end;
var state = _scan(uri, start, end, _uriStart, indices);
// Some states that should be non-simple, but the URI ended early.
// Paths that end at a ".." must be normalized to end in "../".
if (state >= _nonSimpleEndStates) {
indices[_notSimpleIndex] = end;
}
int schemeEnd = indices[_schemeEndIndex];
if (schemeEnd >= start) {
// Rescan the scheme part now that we know it's not a path.
state = _scan(uri, start, schemeEnd, _schemeStart, indices);
if (state == _schemeStart) {
// Empty scheme.
indices[_notSimpleIndex] = schemeEnd;
}
}
// The returned positions are limited by the scanners ability to write only
// one position per character, and only the current position.
// Scanning from left to right, we only know whether something is a scheme
// or a path when we see a `:` or `/`, and likewise we only know if the first
// `/` is part of the path or is leading an authority component when we see
// the next character.
int hostStart = indices[_hostStartIndex] + 1;
int portStart = indices[_portStartIndex];
int pathStart = indices[_pathStartIndex];
int queryStart = indices[_queryStartIndex];
int fragmentStart = indices[_fragmentStartIndex];
// We may discover the scheme while handling special cases.
String? scheme;
// Derive some positions that weren't set to normalize the indices.
if (fragmentStart < queryStart) queryStart = fragmentStart;
// If pathStart isn't set (it's before scheme end or host start), then
// the path is empty, or there is no authority part and the path
// starts with a non-simple character.
if (pathStart < hostStart) {
// There is an authority, but no path. The path would start with `/`
// if it was there.
pathStart = queryStart;
} else if (pathStart <= schemeEnd) {
// There is a scheme, but no authority.
pathStart = schemeEnd + 1;
}
// If there is an authority with no port, set the port position
// to be at the end of the authority (equal to pathStart).
// This also handles a ":" in a user-info component incorrectly setting
// the port start position.
if (portStart < hostStart) portStart = pathStart;
assert(hostStart == start || schemeEnd <= hostStart);
assert(hostStart <= portStart);
assert(schemeEnd <= pathStart);
assert(portStart <= pathStart);
assert(pathStart <= queryStart);
assert(queryStart <= fragmentStart);
bool isSimple = indices[_notSimpleIndex] < start;
if (isSimple) {
// Check/do normalizations that weren't detected by the scanner.
// This includes removal of empty port or userInfo,
// or scheme specific port and path normalizations.
if (hostStart > schemeEnd + 3) {
// Always be non-simple if URI contains user-info.
// The scanner doesn't set the not-simple position in this case because
// it's setting the host-start position instead.
isSimple = false;
} else if (portStart > start && portStart + 1 == pathStart) {
// If the port is empty, it should be omitted.
// Pathological case, don't bother correcting it.
isSimple = false;
} else if (uri.startsWith(r"\", pathStart) ||
hostStart > start &&
(uri.startsWith(r"\", hostStart - 1) ||
uri.startsWith(r"\", hostStart - 2))) {
// Seeing a `\` anywhere.
// The scanner doesn't record when the first path character is a `\`
// or when the last slash before the authority is a `\`.
isSimple = false;
} else if (queryStart < end &&
(queryStart == pathStart + 2 &&
uri.startsWith("..", pathStart)) ||
(queryStart > pathStart + 2 &&
uri.startsWith("/..", queryStart - 3))) {
// The path ends in a ".." segment. This should be normalized to "../".
// We didn't detect this while scanning because a query or fragment was
// detected at the same time (which is why we only need to check this
// if there is something after the path).
isSimple = false;
} else {
// There are a few scheme-based normalizations that
// the scanner couldn't check.
// That means that the input is very close to simple, so just do
// the normalizations.
if (schemeEnd == start + 4) {
// Do scheme based normalizations for file, http.
if (uri.startsWith("file", start)) {
scheme = "file";
if (hostStart <= start) {
// File URIs should have an authority.
// Paths after an authority should be absolute.
String schemeAuth = "file://";
int delta = 2;
if (!uri.startsWith("/", pathStart)) {
schemeAuth = "file:///";
delta = 3;
}
uri = schemeAuth + uri.substring(pathStart, end);
schemeEnd -= start;
hostStart = 7;
portStart = 7;
pathStart = 7;
queryStart += delta - start;
fragmentStart += delta - start;
start = 0;
end = uri.length;
} else if (pathStart == queryStart) {
// Uri has authority and empty path. Add "/" as path.
if (start == 0 && end == uri.length) {
uri = uri.replaceRange(pathStart, queryStart, "/");
queryStart += 1;
fragmentStart += 1;
end += 1;
} else {
uri =
"${uri.substring(start, pathStart)}/"
"${uri.substring(queryStart, end)}";
schemeEnd -= start;
hostStart -= start;
portStart -= start;
pathStart -= start;
queryStart += 1 - start;
fragmentStart += 1 - start;
start = 0;
end = uri.length;
}
}
} else if (uri.startsWith("http", start)) {
scheme = "http";
// HTTP URIs should not have an explicit port of 80.
if (portStart > start &&
portStart + 3 == pathStart &&
uri.startsWith("80", portStart + 1)) {
if (start == 0 && end == uri.length) {
uri = uri.replaceRange(portStart, pathStart, "");
pathStart -= 3;
queryStart -= 3;
fragmentStart -= 3;
end -= 3;
} else {
uri =
uri.substring(start, portStart) +
uri.substring(pathStart, end);
schemeEnd -= start;
hostStart -= start;
portStart -= start;
pathStart -= 3 + start;
queryStart -= 3 + start;
fragmentStart -= 3 + start;
start = 0;
end = uri.length;
}
}
}
} else if (schemeEnd == start + 5 && uri.startsWith("https", start)) {
scheme = "https";
// HTTPS URIs should not have an explicit port of 443.
if (portStart > start &&
portStart + 4 == pathStart &&
uri.startsWith("443", portStart + 1)) {
if (start == 0 && end == uri.length) {
uri = uri.replaceRange(portStart, pathStart, "");
pathStart -= 4;
queryStart -= 4;
fragmentStart -= 4;
end -= 3;
} else {
uri =
uri.substring(start, portStart) +
uri.substring(pathStart, end);
schemeEnd -= start;
hostStart -= start;
portStart -= start;
pathStart -= 4 + start;
queryStart -= 4 + start;
fragmentStart -= 4 + start;
start = 0;
end = uri.length;
}
}
}
}
}
if (isSimple) {
if (start > 0 || end < uri.length) {
uri = uri.substring(start, end);
schemeEnd -= start;
hostStart -= start;
portStart -= start;
pathStart -= start;
queryStart -= start;
fragmentStart -= start;
}
return _SimpleUri(
uri,
schemeEnd,
hostStart,
portStart,
pathStart,
queryStart,
fragmentStart,
scheme,
);
}
return _Uri.notSimple(
uri,
start,
end,
schemeEnd,
hostStart,
portStart,
pathStart,
queryStart,
fragmentStart,
scheme,
);
}parseIPv4Address()
Parses the host as an IP version 4 (IPv4) address, returning the address as a list of 4 bytes in network byte order (big endian).
If start and end are provided, only that range, which must be a valid range of host, is parsed. Defaults to all of host.
Throws a FormatException if (the range of) host is not a valid IPv4 address representation, meaning something of the form <octet>.<octet>.<octet>.<octet> where each octet is a decimal numeral in the range 0..255 with no leading zeros.
Implementation
dart
static List<int> parseIPv4Address(
String host, [
@Since('3.10') int start = 0,
@Since('3.10') int? end,
]) {
end = RangeError.checkValidRange(start, end, host.length);
var list = Uint8List(4);
_parseIPv4Address(host, start, end, list, 0);
return list;
}parseIPv6Address()
Parses the host as an IP version 6 (IPv6) address.
Returns the address as a list of 16 bytes in network byte order (big endian).
Throws a FormatException if host is not a valid IPv6 address representation.
Acts on the substring from start to end. If end is omitted, it defaults to the end of the string.
Some examples of IPv6 addresses:
::1FEDC:BA98:7654:3210:FEDC:BA98:7654:32103ffe:2a00:100:7031::1::FFFF:129.144.52.382010:836B:4179::836B:4179
The grammar for IPv6 addresses are:
dart
IPv6address ::= (h16 ":"){6} ls32
| "::" (h16 ":"){5} ls32
| ( h16) "::" (h16 ":"){4} ls32
| ((h16 ":"){0,1} h16) "::" (h16 ":"){3} ls32
| ((h16 ":"){0,2} h16) "::" (h16 ":"){2} ls32
| ((h16 ":"){0,3} h16) "::" h16 ":" ls32
| ((h16 ":"){0,4} h16) "::" ls32
| ((h16 ":"){0,5} h16) "::" h16
| ((h16 ":"){0,6} h16) "::"
ls32 ::= (h16 ":" h16) | IPv4address
;; least-significant 32 bits of address
h16 ::= HEXDIG{1,4}
;; 16 bits of address represented in hexadecimalThat is
- eight 1-to-4-digit hexadecimal numerals separated by
:, or - one to seven such
:-separated numerals, with either one pair is separated by::, or a leading or trailing::. - either of the above with a trailing two
:-separated numerals replaced by an IPv4 address.
An IPv6 address with a zone ID (from RFC 6874) is an IPv6 address followed by %25 (an escaped %) and valid zone characters.
dart
IPv6addrz ::= IPv6address "%25" ZoneID
ZoneID ::= (unreserved | pct-encoded)+
```.Implementation
dart
static List<int> parseIPv6Address(String host, [int start = 0, int? end]) {
end ??= RangeError.checkValidRange(start, end, host.length);
// An IPv6 address consists of exactly 8 parts of 1-4 hex digits, separated
// by `:`'s, with the following exceptions:
//
// - One (and only one) wildcard (`::`) may be present, representing a fill
// of 0's. The IPv6 `::` is thus 16 bytes of `0`.
// - The last two parts may be replaced by an IPv4 "dotted-quad" address.
// Helper function for reporting a badly formatted IPv6 address.
Never error(String msg, int? position) {
throw FormatException('Illegal IPv6 address, $msg', host, position);
}
if (end - start < 2) error('address is too short', null);
Uint8List result = Uint8List(16);
// Set if seeing a ".", suggesting that there is an IPv4 address.
int partStart = start;
int wildcardAt = -1;
int partCount = 0;
int hexValue = 0;
bool decValue = true;
int cursor = start;
// Handle leading colons eagerly to make the loop simpler.
// After this, any colon encountered will be after another colon or
// a hex part.
if (host.codeUnitAt(cursor) == _COLON) {
if (host.codeUnitAt(cursor + 1) == _COLON) {
wildcardAt = 0;
partCount = 1;
partStart = cursor += 2;
} else {
error('invalid start colon', cursor);
}
}
// Parse all parts, except a potential last one.
while (true) {
var char = cursor >= end ? 0 : host.codeUnitAt(cursor);
handleDigit:
{
int hexDigit;
if (char ^ _DIGIT_0 case var digit when digit <= 9) {
hexDigit = digit;
} else if (char | 0x20 case var letter
when letter >= _LOWER_CASE_A && letter <= _LOWER_CASE_F) {
hexDigit = letter - (_LOWER_CASE_A - 10);
decValue = false;
} else {
break handleDigit; // Not a digit.
}
if (cursor < partStart + 4) {
hexValue = hexValue * 16 + hexDigit;
cursor++;
continue;
}
error('an IPv6 part can contain a maximum of 4 hex digits', partStart);
}
if (cursor > partStart) {
// Non-empty part, value in hexValue.
if (char == _DOT) {
if (decValue) {
if (partCount <= 6) {
_parseIPv4Address(host, partStart, end, result, partCount * 2);
cursor = end; // Throws if IPv4 does not extend to end.
partCount += 2;
break; // Must be last.
}
error('an address must contain at most 8 parts', partStart);
}
break; // Any other dot is just an invalid character.
}
// Non-empty hex part.
result[partCount * 2] = hexValue >> 8;
result[partCount * 2 + 1] = hexValue & 0xFF;
partCount++;
if (char == _COLON) {
if (partCount < 8) {
// Start new part.
hexValue = 0;
decValue = true;
cursor++;
partStart = cursor;
continue;
}
error('an address must contain at most 8 parts', cursor);
}
break; // Unexpected character or the end sentinel.
}
// Empty part, after a colon.
if (char == _COLON) {
// Colon after empty part must be after colon.
// (Leading colons were checked before loop.)
if (wildcardAt < 0) {
wildcardAt = partCount;
partCount++; // A wildcard fills at least one part.
partStart = ++cursor;
continue;
}
error('only one wildcard `::` is allowed', cursor);
}
// Missing hex digits after colon.
// OK to end right after wildcard, not after another colon.
if (wildcardAt != partCount - 1) {
// Missing part after a single `:`.
// Error even at end.
error('missing part', cursor);
}
break; // Error if not at end.
}
if (cursor < end) error('invalid character', cursor);
if (partCount < 8) {
if (wildcardAt < 0) {
error(
'an address without a wildcard must contain exactly 8 parts',
end,
);
}
// Move everything after the wildcard to the end of the buffer, and fill
// the wildcard gap with zeros.
var partAfterWildcard = wildcardAt + 1;
int partsAfterWildcard = partCount - partAfterWildcard;
if (partsAfterWildcard > 0) {
var positionAfterWildcard = partAfterWildcard * 2;
var bytesAfterWildcard = partsAfterWildcard * 2;
var newPositionAfterWildcard = result.length - bytesAfterWildcard;
result.setRange(
newPositionAfterWildcard,
result.length,
result,
positionAfterWildcard,
);
result.fillRange(positionAfterWildcard, newPositionAfterWildcard, 0);
}
}
return result;
}splitQueryString()
Splits the query into a map according to the rules specified for FORM post in the HTML 4.01 specification section 17.13.4.
Each key and value in the returned map has been decoded. If the query is the empty string, an empty map is returned.
Keys in the query string that have no value are mapped to the empty string.
Each query component will be decoded using encoding. The default encoding is UTF-8.
Example:
dart
final queryStringMap =
Uri.splitQueryString('limit=10&max=100&search=Dart%20is%20fun');
print(jsonEncode(queryStringMap));
// {"limit":"10","max":"100","search":"Dart is fun"}Implementation
dart
static Map<String, String> splitQueryString(
String query, {
Encoding encoding = utf8,
}) {
return query.split("&").fold({}, (map, element) {
int index = element.indexOf("=");
if (index == -1) {
if (element != "") {
map[decodeQueryComponent(element, encoding: encoding)] = "";
}
} else if (index != 0) {
var key = element.substring(0, index);
var value = element.substring(index + 1);
map[decodeQueryComponent(key, encoding: encoding)] =
decodeQueryComponent(value, encoding: encoding);
}
return map;
});
}tryParse()
Creates a new Uri object by parsing a URI string.
If start and end are provided, they must specify a valid substring of uri, and only the substring from start to end is parsed as a URI.
Returns null if the uri string is not valid as a URI or URI reference.
Example:
dart
final uri = Uri.tryParse(
'https://dart.dev/libraries/dart-core#utility-classes', 0, 16);
print(uri); // https://dart.dev
var notUri = Uri.tryParse('::Not valid URI::');
print(notUri); // nullImplementation
dart
static Uri? tryParse(String uri, [int start = 0, int? end]) {
// TODO: Optimize to avoid throwing-and-recatching.
try {
return parse(uri, start, end);
} on FormatException {
return null;
}
}