| Index: sdk/lib/core/uri.dart
|
| diff --git a/sdk/lib/core/uri.dart b/sdk/lib/core/uri.dart
|
| index 78f42de6bdd52bbf322cd55c9ab71673557bbad9..2cd5f8a5a8981a6a23e1d70aae921e8d795ee48f 100644
|
| --- a/sdk/lib/core/uri.dart
|
| +++ b/sdk/lib/core/uri.dart
|
| @@ -16,18 +16,8 @@ part of dart.core;
|
| * [libtour]: http://www.dartlang.org/docs/dart-up-and-running/contents/ch03.html
|
| */
|
| class Uri {
|
| - // The host name of the URI.
|
| - // Set to `null` if there is no authority in a URI.
|
| - final String _host;
|
| - // The port. Set to null if there is no port. Normalized to null if
|
| - // the port is the default port for the scheme.
|
| - // Set to the value of the default port if an empty port was supplied.
|
| - int _port;
|
| - // The path. Always non-null.
|
| - String _path;
|
| -
|
| /**
|
| - * Returns the scheme component.
|
| + * The scheme component of the URI.
|
| *
|
| * Returns the empty string if there is no scheme component.
|
| *
|
| @@ -39,6 +29,213 @@ class Uri {
|
| final String scheme;
|
|
|
| /**
|
| + * The user-info part of the authority.
|
| + *
|
| + * Does not distinguish between an empty user-info and an absent one.
|
| + * The value is always non-null.
|
| + * Is considered absent if [_host] is `null`.
|
| + */
|
| + final String _userInfo;
|
| +
|
| + /**
|
| + * The host name of the URI.
|
| + *
|
| + * Set to `null` if there is no authority in the URI.
|
| + * The host name is the only mandatory part of an authority, so we use
|
| + * it to mark whether an authority part was present or not.
|
| + */
|
| + final String _host;
|
| +
|
| + /**
|
| + * The port number part of the authority.
|
| + *
|
| + * The port. Set to null if there is no port. Normalized to null if
|
| + * the port is the default port for the scheme.
|
| + */
|
| + int _port;
|
| +
|
| + /**
|
| + * The path of the URI.
|
| + *
|
| + * Always non-null.
|
| + */
|
| + String _path;
|
| +
|
| + // The query content, or null if there is no query.
|
| + final String _query;
|
| +
|
| + // The fragment content, or null if there is no fragment.
|
| + final String _fragment;
|
| +
|
| + /**
|
| + * Cache the computed return value of [pathSegements].
|
| + */
|
| + List<String> _pathSegments;
|
| +
|
| + /**
|
| + * Cache the computed return value of [queryParameters].
|
| + */
|
| + Map<String, String> _queryParameters;
|
| +
|
| + /// Internal non-verifying constructor. Only call with validated arguments.
|
| + Uri._internal(this.scheme,
|
| + this._userInfo,
|
| + this._host,
|
| + this._port,
|
| + this._path,
|
| + this._query,
|
| + this._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 will have an autority 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.
|
| + * 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
|
| + * calls for 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. The
|
| + * percent-encoding of the keys and values encodes all characters
|
| + * except for the unreserved characters.
|
| + * If `query` is the empty string, it is equivalent to omitting it.
|
| + * To have an actual empty query part,
|
| + * use an empty list for `queryParameters`.
|
| + * If both `query` and `queryParameters` are omitted or `null`, the
|
| + * URI will have no query part.
|
| + *
|
| + * The fragment component is set through [fragment].
|
| + * It should be a valid URI fragment, but invalid characters other than
|
| + * general delimiters, will be escaped if necessary.
|
| + * If `fragment` is omitted or `null`, the URI will have no fragment part.
|
| + */
|
| + factory Uri({String scheme : "",
|
| + String userInfo : "",
|
| + String host,
|
| + int port,
|
| + String path,
|
| + Iterable<String> pathSegments,
|
| + String query,
|
| + Map<String, String> queryParameters,
|
| + String fragment}) {
|
| + scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
|
| + userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
|
| + host = _makeHost(host, 0, _stringOrNullLength(host), false);
|
| + // Special case this constructor for backwards compatibility.
|
| + if (query == "") query = null;
|
| + query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
|
| + fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment));
|
| + port = _makePort(port, scheme);
|
| + bool isFile = (scheme == "file");
|
| + if (host == null &&
|
| + (userInfo.isNotEmpty || port != null || isFile)) {
|
| + host = "";
|
| + }
|
| + bool hasAuthority = (host != null);
|
| + path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
|
| + scheme, hasAuthority);
|
| + if (scheme.isEmpty && host == null && !path.startsWith('/')) {
|
| + path = _normalizeRelativePath(path);
|
| + } else {
|
| + path = _removeDotSegments(path);
|
| + }
|
| + return new Uri._internal(scheme, userInfo, host, port,
|
| + path, query, fragment);
|
| + }
|
| +
|
| + /**
|
| + * Creates a new `http` URI from authority, path and query.
|
| + *
|
| + * Examples:
|
| + *
|
| + * ```
|
| + * // http://example.org/path?q=dart.
|
| + * new Uri.http("google.com", "/search", { "q" : "dart" });
|
| + *
|
| + * // http://user:pass@localhost:8080
|
| + * new Uri.http("user:pass@localhost:8080", "");
|
| + *
|
| + * // http://example.org/a%20b
|
| + * new Uri.http("example.org", "a b");
|
| + *
|
| + * // http://example.org/a%252F
|
| + * new Uri.http("example.org", "/a%2F");
|
| + * ```
|
| + *
|
| + * The `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` will have no authority, and will not be 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.
|
| + *
|
| + * The `query` component is set from the optional [queryParameters]
|
| + * argument.
|
| + */
|
| + factory Uri.http(String authority,
|
| + String unencodedPath,
|
| + [Map<String, String> queryParameters]) {
|
| + return _makeHttpUri("http", authority, unencodedPath, 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`.
|
| + */
|
| + factory Uri.https(String authority,
|
| + String unencodedPath,
|
| + [Map<String, String> queryParameters]) {
|
| + return _makeHttpUri("https", authority, unencodedPath, queryParameters);
|
| + }
|
| +
|
| + /**
|
| * Returns the authority component.
|
| *
|
| * The authority is formatted from the [userInfo], [host] and [port]
|
| @@ -54,14 +251,6 @@ class Uri {
|
| }
|
|
|
| /**
|
| - * The user-info part of the authority.
|
| - *
|
| - * Does not distinguish between an empty user-info and an absent one.
|
| - * The value is always non-null.
|
| - */
|
| - final String _userInfo;
|
| -
|
| - /**
|
| * Returns the user info part of the authority component.
|
| *
|
| * Returns the empty string if there is no user info in the
|
| @@ -118,9 +307,6 @@ class Uri {
|
| */
|
| String get path => _path;
|
|
|
| - // The query content, or null if there is no query.
|
| - final String _query;
|
| -
|
| /**
|
| * Returns the query component. The returned query is encoded. To get
|
| * direct access to the decoded query use [queryParameters].
|
| @@ -129,9 +315,6 @@ class Uri {
|
| */
|
| String get query => (_query == null) ? "" : _query;
|
|
|
| - // The fragment content, or null if there is no fragment.
|
| - final String _fragment;
|
| -
|
| /**
|
| * Returns the fragment identifier component.
|
| *
|
| @@ -141,16 +324,6 @@ class Uri {
|
| String get fragment => (_fragment == null) ? "" : _fragment;
|
|
|
| /**
|
| - * Cache the computed return value of [pathSegements].
|
| - */
|
| - List<String> _pathSegments;
|
| -
|
| - /**
|
| - * Cache the computed return value of [queryParameters].
|
| - */
|
| - Map<String, String> _queryParameters;
|
| -
|
| - /**
|
| * Creates a new `Uri` object by parsing a URI string.
|
| *
|
| * If [start] and [end] are provided, only the substring from `start`
|
| @@ -415,164 +588,6 @@ class Uri {
|
| throw new FormatException(message, uri, index);
|
| }
|
|
|
| - /// Internal non-verifying constructor. Only call with validated arguments.
|
| - Uri._internal(this.scheme,
|
| - this._userInfo,
|
| - this._host,
|
| - this._port,
|
| - this._path,
|
| - this._query,
|
| - this._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 will have an autority 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.
|
| - * 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
|
| - * calls for 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. The
|
| - * percent-encoding of the keys and values encodes all characters
|
| - * except for the unreserved characters.
|
| - * If `query` is the empty string, it is equivalent to omitting it.
|
| - * To have an actual empty query part,
|
| - * use an empty list for `queryParameters`.
|
| - * If both `query` and `queryParameters` are omitted or `null`, the
|
| - * URI will have no query part.
|
| - *
|
| - * The fragment component is set through [fragment].
|
| - * It should be a valid URI fragment, but invalid characters other than
|
| - * general delimiters, will be escaped if necessary.
|
| - * If `fragment` is omitted or `null`, the URI will have no fragment part.
|
| - */
|
| - factory Uri({String scheme : "",
|
| - String userInfo : "",
|
| - String host,
|
| - int port,
|
| - String path,
|
| - Iterable<String> pathSegments,
|
| - String query,
|
| - Map<String, String> queryParameters,
|
| - String fragment}) {
|
| - scheme = _makeScheme(scheme, 0, _stringOrNullLength(scheme));
|
| - userInfo = _makeUserInfo(userInfo, 0, _stringOrNullLength(userInfo));
|
| - host = _makeHost(host, 0, _stringOrNullLength(host), false);
|
| - // Special case this constructor for backwards compatibility.
|
| - if (query == "") query = null;
|
| - query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
|
| - fragment = _makeFragment(fragment, 0, _stringOrNullLength(fragment));
|
| - port = _makePort(port, scheme);
|
| - bool isFile = (scheme == "file");
|
| - if (host == null &&
|
| - (userInfo.isNotEmpty || port != null || isFile)) {
|
| - host = "";
|
| - }
|
| - bool hasAuthority = (host != null);
|
| - path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
|
| - scheme, hasAuthority);
|
| - if (scheme.isEmpty && host == null && !path.startsWith('/')) {
|
| - path = _normalizeRelativePath(path);
|
| - } else {
|
| - path = _removeDotSegments(path);
|
| - }
|
| - return new Uri._internal(scheme, userInfo, host, port,
|
| - path, query, fragment);
|
| - }
|
| -
|
| - /**
|
| - * Creates a new `http` URI from authority, path and query.
|
| - *
|
| - * Examples:
|
| - *
|
| - * ```
|
| - * // http://example.org/path?q=dart.
|
| - * new Uri.http("google.com", "/search", { "q" : "dart" });
|
| - *
|
| - * // http://user:pass@localhost:8080
|
| - * new Uri.http("user:pass@localhost:8080", "");
|
| - *
|
| - * // http://example.org/a%20b
|
| - * new Uri.http("example.org", "a b");
|
| - *
|
| - * // http://example.org/a%252F
|
| - * new Uri.http("example.org", "/a%2F");
|
| - * ```
|
| - *
|
| - * The `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` will have no authority, and will not be 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.
|
| - *
|
| - * The `query` component is set from the optional [queryParameters]
|
| - * argument.
|
| - */
|
| - factory Uri.http(String authority,
|
| - String unencodedPath,
|
| - [Map<String, String> queryParameters]) {
|
| - return _makeHttpUri("http", authority, unencodedPath, 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`.
|
| - */
|
| - factory Uri.https(String authority,
|
| - String unencodedPath,
|
| - [Map<String, String> queryParameters]) {
|
| - return _makeHttpUri("https", authority, unencodedPath, queryParameters);
|
| - }
|
| -
|
| static Uri _makeHttpUri(String scheme,
|
| String authority,
|
| String unencodedPath,
|
| @@ -938,7 +953,7 @@ class Uri {
|
| if (userInfo != null) {
|
| userInfo = _makeUserInfo(userInfo, 0, userInfo.length);
|
| } else {
|
| - userInfo = this.userInfo;
|
| + userInfo = this._userInfo;
|
| }
|
| if (port != null) {
|
| port = _makePort(port, scheme);
|
| @@ -952,7 +967,7 @@ class Uri {
|
| if (host != null) {
|
| host = _makeHost(host, 0, host.length, false);
|
| } else if (this.hasAuthority) {
|
| - host = this.host;
|
| + host = this._host;
|
| } else if (userInfo.isNotEmpty || port != null || isFile) {
|
| host = "";
|
| }
|
| @@ -962,7 +977,7 @@ class Uri {
|
| path = _makePath(path, 0, _stringOrNullLength(path), pathSegments,
|
| scheme, hasAuthority);
|
| } else {
|
| - path = this.path;
|
| + path = this._path;
|
| if ((isFile || (hasAuthority && !path.isEmpty)) &&
|
| !path.startsWith('/')) {
|
| path = "/" + path;
|
| @@ -971,14 +986,14 @@ class Uri {
|
|
|
| if (query != null || queryParameters != null) {
|
| query = _makeQuery(query, 0, _stringOrNullLength(query), queryParameters);
|
| - } else if (this.hasQuery) {
|
| - query = this.query;
|
| + } else {
|
| + query = this._query;
|
| }
|
|
|
| if (fragment != null) {
|
| fragment = _makeFragment(fragment, 0, fragment.length);
|
| - } else if (this.hasFragment) {
|
| - fragment = this.fragment;
|
| + } else {
|
| + fragment = this._fragment;
|
| }
|
|
|
| return new Uri._internal(
|
| @@ -992,7 +1007,8 @@ class Uri {
|
| */
|
| Uri removeFragment() {
|
| if (!this.hasFragment) return this;
|
| - return new Uri._internal(scheme, userInfo, host, port, path, query, null);
|
| + return new Uri._internal(scheme, _userInfo, _host, _port,
|
| + _path, _query, null);
|
| }
|
|
|
| /**
|
|
|