Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(736)

Unified Diff: sdk/lib/core/uri.dart

Issue 1396973004: Fix bug in Uri.removeFragment. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/corelib/uri_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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);
}
/**
« no previous file with comments | « no previous file | tests/corelib/uri_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698