Dart API Referencedart:uriUri

Uri class

A parsed URI, inspired by Closure's URI class. Implements RFC-3986.

class Uri {
  final String scheme;
  final String userInfo;
  final String domain;
  final int port;
  final String path;
  final String query;
  final String fragment;

  Uri.fromString(String uri) : this._fromMatch(_splitRe.firstMatch(uri));

  Uri._fromMatch(Match m) :
    this.fromComponents(scheme: _emptyIfNull(m[_COMPONENT_SCHEME]),
                        userInfo: _emptyIfNull(m[_COMPONENT_USER_INFO]),
                        domain: _emptyIfNull(m[_COMPONENT_DOMAIN]),
                        port: _parseIntOrZero(m[_COMPONENT_PORT]),
                        path: _emptyIfNull(m[_COMPONENT_PATH]),
                        query: _emptyIfNull(m[_COMPONENT_QUERY_DATA]),
                        fragment: _emptyIfNull(m[_COMPONENT_FRAGMENT]));

  const Uri.fromComponents({this.scheme: "",
                            this.userInfo: "",
                            this.domain: "",
                            this.port: 0,
                            this.path: "",
                            this.query: "",
                            this.fragment: ""});

  Uri(String uri) : this.fromString(uri);

  static String _emptyIfNull(String val) => val != null ? val : '';

  static int _parseIntOrZero(String val) {
    if (val !== null && val != '') {
      return int.parse(val);
    } else {
      return 0;
    }
  }

  // NOTE: This code was ported from: closure-library/closure/goog/uri/utils.js
  static const RegExp _splitRe = const RegExp(
      '^'
      '(?:'
        '([^:/?#.]+)'                   // scheme - ignore special characters
                                        // used by other URL parts such as :,
                                        // ?, /, #, and .
      ':)?'
      '(?://'
        '(?:([^/?#]*)@)?'               // userInfo
        '([\\w\\d\\-\\u0100-\\uffff.%]*)'
                                        // domain - restrict to letters,
                                        // digits, dashes, dots, percent
                                        // escapes, and unicode characters.
        '(?::([0-9]+))?'                // port
      ')?'
      '([^?#]+)?'                       // path
      '(?:\\?([^#]*))?'                 // query
      '(?:#(.*))?'                      // fragment
      '\$');

  static const _COMPONENT_SCHEME = 1;
  static const _COMPONENT_USER_INFO = 2;
  static const _COMPONENT_DOMAIN = 3;
  static const _COMPONENT_PORT = 4;
  static const _COMPONENT_PATH = 5;
  static const _COMPONENT_QUERY_DATA = 6;
  static const _COMPONENT_FRAGMENT = 7;

  /**
   * Returns `true` if the URI is absolute.
   */
  bool isAbsolute() {
    if ("" == scheme) return false;
    if ("" != fragment) return false;
    return true;

    /* absolute-URI  = scheme ":" hier-part [ "?" query ]
     * hier-part   = "//" authority path-abempty
     *             / path-absolute
     *             / path-rootless
     *             / path-empty
     *
     * 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 / ":" / "@"
     */
  }

  Uri resolve(String uri) {
    return resolveUri(new Uri.fromString(uri));
  }

  Uri resolveUri(Uri reference) {
    // From RFC 3986.
    String targetScheme;
    String targetUserInfo;
    String targetDomain;
    int targetPort;
    String targetPath;
    String targetQuery;
    if (reference.scheme != "") {
      targetScheme = reference.scheme;
      targetUserInfo = reference.userInfo;
      targetDomain = reference.domain;
      targetPort = reference.port;
      targetPath = removeDotSegments(reference.path);
      targetQuery = reference.query;
    } else {
      if (reference.hasAuthority()) {
        targetUserInfo = reference.userInfo;
        targetDomain = reference.domain;
        targetPort = reference.port;
        targetPath = removeDotSegments(reference.path);
        targetQuery = reference.query;
      } else {
        if (reference.path == "") {
          targetPath = this.path;
          if (reference.query != "") {
            targetQuery = reference.query;
          } else {
            targetQuery = this.query;
          }
        } else {
          if (reference.path.startsWith("/")) {
            targetPath = removeDotSegments(reference.path);
          } else {
            targetPath = removeDotSegments(merge(this.path, reference.path));
          }
          targetQuery = reference.query;
        }
        targetUserInfo = this.userInfo;
        targetDomain = this.domain;
        targetPort = this.port;
      }
      targetScheme = this.scheme;
    }
    return new Uri.fromComponents(scheme: targetScheme,
                                  userInfo: targetUserInfo,
                                  domain: targetDomain,
                                  port: targetPort,
                                  path: targetPath,
                                  query: targetQuery,
                                  fragment: reference.fragment);
  }

  bool hasAuthority() {
    return (userInfo != "") || (domain != "") || (port != 0);
  }

  /**
   * For http/https schemes returns URI's [origin][] - scheme://domain:port.
   * For all other schemes throws ArgumentError.
   * [origin]: http://www.w3.org/TR/2011/WD-html5-20110405/origin-0.html#origin
   */
  String get origin {
    if (scheme == "") {
      // TODO(aprelev@gmail.com): Use StateException instead
      throw new ArgumentError("Cannot use origin without a scheme");
    }
    if (scheme != "http" && scheme != "https") {
      // TODO(aprelev@gmail.com): Use StateException instead
      throw new ArgumentError(
        "origin is applicable to http/https schemes only. Not \'$scheme\'");
    }
    StringBuffer sb = new StringBuffer();
    sb.add(scheme);
    sb.add(":");
    if (domain == null || domain == "") {
      // TODO(aprelev@gmail.com): Use StateException instead
      throw new ArgumentError("Cannot use origin without a domain");
    }

    sb.add("//");
    sb.add(domain);
    if (port != 0) {
      sb.add(":");
      sb.add(port);
    }
    return sb.toString();
  }

  String toString() {
    StringBuffer sb = new StringBuffer();
    _addIfNonEmpty(sb, scheme, scheme, ':');
    if (hasAuthority() || (scheme == "file")) {
      sb.add("//");
      _addIfNonEmpty(sb, userInfo, userInfo, "@");
      sb.add(domain === null ? "null" : domain);
      if (port != 0) {
        sb.add(":");
        sb.add(port.toString());
      }
    }
    sb.add(path === null ? "null" : path);
    _addIfNonEmpty(sb, query, "?", query);
    _addIfNonEmpty(sb, fragment, "#", fragment);
    return sb.toString();
  }

  static void _addIfNonEmpty(StringBuffer sb, String test,
                             String first, String second) {
    if ("" != test) {
      sb.add(first === null ? "null" : first);
      sb.add(second === null ? "null" : second);
    }
  }
}

Constructors

new Uri(String uri) #

Uri(String uri) : this.fromString(uri);

const Uri.fromComponents([String scheme = "", String userInfo = "", String domain = "", int port = 0, String path = "", String query = "", String fragment = ""]) #

const Uri.fromComponents({this.scheme: "",
                          this.userInfo: "",
                          this.domain: "",
                          this.port: 0,
                          this.path: "",
                          this.query: "",
                          this.fragment: ""});

new Uri.fromString(String uri) #

Uri.fromString(String uri) : this._fromMatch(_splitRe.firstMatch(uri));

Properties

final String domain #

final String domain;

final String fragment #

final String fragment;

final String origin #

For http/https schemes returns URI's origin - scheme://domain:port. For all other schemes throws ArgumentError.

String get origin {
  if (scheme == "") {
    // TODO(aprelev@gmail.com): Use StateException instead
    throw new ArgumentError("Cannot use origin without a scheme");
  }
  if (scheme != "http" && scheme != "https") {
    // TODO(aprelev@gmail.com): Use StateException instead
    throw new ArgumentError(
      "origin is applicable to http/https schemes only. Not \'$scheme\'");
  }
  StringBuffer sb = new StringBuffer();
  sb.add(scheme);
  sb.add(":");
  if (domain == null || domain == "") {
    // TODO(aprelev@gmail.com): Use StateException instead
    throw new ArgumentError("Cannot use origin without a domain");
  }

  sb.add("//");
  sb.add(domain);
  if (port != 0) {
    sb.add(":");
    sb.add(port);
  }
  return sb.toString();
}

final String path #

final String path;

final int port #

final int port;

final String query #

final String query;

final String scheme #

final String scheme;

final String userInfo #

final String userInfo;

Methods

bool hasAuthority() #

bool hasAuthority() {
  return (userInfo != "") || (domain != "") || (port != 0);
}

bool isAbsolute() #

Returns true if the URI is absolute.

bool isAbsolute() {
  if ("" == scheme) return false;
  if ("" != fragment) return false;
  return true;

  /* absolute-URI  = scheme ":" hier-part [ "?" query ]
   * hier-part   = "//" authority path-abempty
   *             / path-absolute
   *             / path-rootless
   *             / path-empty
   *
   * 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 / ":" / "@"
   */
}

Uri resolve(String uri) #

Uri resolve(String uri) {
  return resolveUri(new Uri.fromString(uri));
}

Uri resolveUri(Uri reference) #

Uri resolveUri(Uri reference) {
  // From RFC 3986.
  String targetScheme;
  String targetUserInfo;
  String targetDomain;
  int targetPort;
  String targetPath;
  String targetQuery;
  if (reference.scheme != "") {
    targetScheme = reference.scheme;
    targetUserInfo = reference.userInfo;
    targetDomain = reference.domain;
    targetPort = reference.port;
    targetPath = removeDotSegments(reference.path);
    targetQuery = reference.query;
  } else {
    if (reference.hasAuthority()) {
      targetUserInfo = reference.userInfo;
      targetDomain = reference.domain;
      targetPort = reference.port;
      targetPath = removeDotSegments(reference.path);
      targetQuery = reference.query;
    } else {
      if (reference.path == "") {
        targetPath = this.path;
        if (reference.query != "") {
          targetQuery = reference.query;
        } else {
          targetQuery = this.query;
        }
      } else {
        if (reference.path.startsWith("/")) {
          targetPath = removeDotSegments(reference.path);
        } else {
          targetPath = removeDotSegments(merge(this.path, reference.path));
        }
        targetQuery = reference.query;
      }
      targetUserInfo = this.userInfo;
      targetDomain = this.domain;
      targetPort = this.port;
    }
    targetScheme = this.scheme;
  }
  return new Uri.fromComponents(scheme: targetScheme,
                                userInfo: targetUserInfo,
                                domain: targetDomain,
                                port: targetPort,
                                path: targetPath,
                                query: targetQuery,
                                fragment: reference.fragment);
}

String toString() #

Returns a string representation of this object.

docs inherited from Object
String toString() {
  StringBuffer sb = new StringBuffer();
  _addIfNonEmpty(sb, scheme, scheme, ':');
  if (hasAuthority() || (scheme == "file")) {
    sb.add("//");
    _addIfNonEmpty(sb, userInfo, userInfo, "@");
    sb.add(domain === null ? "null" : domain);
    if (port != 0) {
      sb.add(":");
      sb.add(port.toString());
    }
  }
  sb.add(path === null ? "null" : path);
  _addIfNonEmpty(sb, query, "?", query);
  _addIfNonEmpty(sb, fragment, "#", fragment);
  return sb.toString();
}