diff options
Diffstat (limited to 'src/ng/urlUtils.js')
| -rw-r--r-- | src/ng/urlUtils.js | 207 | 
1 files changed, 94 insertions, 113 deletions
| diff --git a/src/ng/urlUtils.js b/src/ng/urlUtils.js index f1e31d7a..50156e6b 100644 --- a/src/ng/urlUtils.js +++ b/src/ng/urlUtils.js @@ -1,119 +1,100 @@  'use strict'; +// NOTE:  The usage of window and document instead of $window and $document here is +// deliberate.  This service depends on the specific behavior of anchor nodes created by the +// browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and +// cause us to break tests.  In addition, when the browser resolves a URL for XHR, it +// doesn't know about mocked locations and resolves URLs to the real document - which is +// exactly the behavior needed here.  There is little value is mocking these out for this +// service. +var urlParsingNode = document.createElement("a"); +var originUrl = urlResolve(window.location.href, true); -function $$UrlUtilsProvider() { -  this.$get = [function() { -    var urlParsingNode = document.createElement("a"), -        // NOTE:  The usage of window and document instead of $window and $document here is -        // deliberate.  This service depends on the specific behavior of anchor nodes created by the -        // browser (resolving and parsing URLs) that is unlikely to be provided by mock objects and -        // cause us to break tests.  In addition, when the browser resolves a URL for XHR, it -        // doesn't know about mocked locations and resolves URLs to the real document - which is -        // exactly the behavior needed here.  There is little value is mocking these our for this -        // service. -        originUrl = resolve(window.location.href, true); +/** + * + * Implementation Notes for non-IE browsers + * ---------------------------------------- + * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, + * results both in the normalizing and parsing of the URL.  Normalizing means that a relative + * URL will be resolved into an absolute URL in the context of the application document. + * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related + * properties are all populated to reflect the normalized URL.  This approach has wide + * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See + * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + * + * Implementation Notes for IE + * --------------------------- + * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other + * browsers.  However, the parsed components will not be set if the URL assigned did not specify + * them.  (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.)  We + * work around that by performing the parsing in a 2nd step by taking a previously normalized + * URL (e.g. by assining to a.href) and assigning it a.href again.  This correctly populates the + * properties such as protocol, hostname, port, etc. + * + * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one + * uses the inner HTML approach to assign the URL as part of an HTML snippet - + * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL. + * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. + * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that + * method and IE < 8 is unsupported. + * + * References: + *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement + *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html + *   http://url.spec.whatwg.org/#urlutils + *   https://github.com/angular/angular.js/pull/2902 + *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ + * + * @function + * @param {string} url The URL to be parsed. + * @description Normalizes and parses a URL. + * @returns {object} Returns the normalized URL as a dictionary. + * + *   | member name   | Description    | + *   |---------------|----------------| + *   | href          | A normalized version of the provided URL if it was not an absolute URL | + *   | protocol      | The protocol including the trailing colon                              | + *   | host          | The host and port (if the port is non-default) of the normalizedUrl    | + *   | search        | The search params, minus the question mark                             | + *   | hash          | The hash string, minus the hash symbol + *   | hostname      | The hostname + *   | port          | The port, without ":" + *   | pathname      | The pathname, beginning with "/" + * + */ +function urlResolve(url) { +  var href = url; +  if (msie) { +    // Normalize before parse.  Refer Implementation Notes on why this is +    // done in two steps on IE. +    urlParsingNode.setAttribute("href", href); +    href = urlParsingNode.href; +  } -    /** -     * @description -     * Normalizes and optionally parses a URL. -     * -     * NOTE:  This is a private service.  The API is subject to change unpredictably in any commit. -     * -     * Implementation Notes for non-IE browsers -     * ---------------------------------------- -     * Assigning a URL to the href property of an anchor DOM node, even one attached to the DOM, -     * results both in the normalizing and parsing of the URL.  Normalizing means that a relative -     * URL will be resolved into an absolute URL in the context of the application document. -     * Parsing means that the anchor node's host, hostname, protocol, port, pathname and related -     * properties are all populated to reflect the normalized URL.  This approach has wide -     * compatibility - Safari 1+, Mozilla 1+, Opera 7+,e etc.  See -     * http://www.aptana.com/reference/html/api/HTMLAnchorElement.html -     * -     * Implementation Notes for IE -     * --------------------------- -     * IE >= 8 and <= 10 normalizes the URL when assigned to the anchor node similar to the other -     * browsers.  However, the parsed components will not be set if the URL assigned did not specify -     * them.  (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.)  We -     * work around that by performing the parsing in a 2nd step by taking a previously normalized -     * URL (e.g. by assining to a.href) and assigning it a.href again.  This correctly populates the -     * properties such as protocol, hostname, port, etc. -     * -     * IE7 does not normalize the URL when assigned to an anchor node.  (Apparently, it does, if one -     * uses the inner HTML approach to assign the URL as part of an HTML snippet - -     * http://stackoverflow.com/a/472729)  However, setting img[src] does normalize the URL. -     * Unfortunately, setting img[src] to something like "javascript:foo" on IE throws an exception. -     * Since the primary usage for normalizing URLs is to sanitize such URLs, we can't use that -     * method and IE < 8 is unsupported. -     * -     * References: -     *   http://developer.mozilla.org/en-US/docs/Web/API/HTMLAnchorElement -     *   http://www.aptana.com/reference/html/api/HTMLAnchorElement.html -     *   http://url.spec.whatwg.org/#urlutils -     *   https://github.com/angular/angular.js/pull/2902 -     *   http://james.padolsey.com/javascript/parsing-urls-with-the-dom/ -     * -     * @param {string} url The URL to be parsed. -     * @param {boolean=} parse When true, returns an object for the parsed URL.  Otherwise, returns -     *   a single string that is the normalized URL. -     * @returns {object|string} When parse is true, returns the normalized URL as a string. -     * Otherwise, returns an object with the following members. -     * -     *   | member name   | Description    | -     *   |---------------|----------------| -     *   | href          | A normalized version of the provided URL if it was not an absolute URL | -     *   | protocol      | The protocol including the trailing colon                              | -     *   | host          | The host and port (if the port is non-default) of the normalizedUrl    | -     * -     * These fields from the UrlUtils interface are currently not needed and hence not returned. -     * -     *   | member name   | Description    | -     *   |---------------|----------------| -     *   | hostname      | The host without the port of the normalizedUrl                         | -     *   | pathname      | The path following the host in the normalizedUrl                       | -     *   | hash          | The URL hash if present                                                | -     *   | search        | The query string                                                       | -     * -     */ -    function resolve(url, parse) { -      var href = url; -      if (msie <= 11) { -        // Normalize before parse.  Refer Implementation Notes on why this is -        // done in two steps on IE. -        urlParsingNode.setAttribute("href", href); -        href = urlParsingNode.href; -      } -      urlParsingNode.setAttribute('href', href); +  urlParsingNode.setAttribute('href', href); + +  // $$urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils +  return { +    href: urlParsingNode.href, +    protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', +    host: urlParsingNode.host, +    search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', +    hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', +    hostname: urlParsingNode.hostname, +    port: urlParsingNode.port, +    pathname: urlParsingNode.pathname && urlParsingNode.pathname.charAt(0) === '/' ? urlParsingNode.pathname : '/' + urlParsingNode.pathname +  }; +} -      if (!parse) { -        return urlParsingNode.href; -      } -      // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils -      return { -        href: urlParsingNode.href, -        protocol: urlParsingNode.protocol, -        host: urlParsingNode.host -        // Currently unused and hence commented out. -        // hostname: urlParsingNode.hostname, -        // port: urlParsingNode.port, -        // pathname: urlParsingNode.pathname, -        // hash: urlParsingNode.hash, -        // search: urlParsingNode.search -      }; -    } -    return { -      resolve: resolve, -      /** -       * Parse a request URL and determine whether this is a same-origin request as the application document. -       * -       * @param {string|object} requestUrl The url of the request as a string that will be resolved -       * or a parsed URL object. -       * @returns {boolean} Whether the request is for the same origin as the application document. -       */ -      isSameOrigin: function isSameOrigin(requestUrl) { -        var parsed = (typeof requestUrl === 'string') ? resolve(requestUrl, true) : requestUrl; -        return (parsed.protocol === originUrl.protocol && -                parsed.host === originUrl.host); -      } -    }; -  }]; +/** + * Parse a request URL and determine whether this is a same-origin request as the application document. + * + * @param {string|object} requestUrl The url of the request as a string that will be resolved + * or a parsed URL object. + * @returns {boolean} Whether the request is for the same origin as the application document. + */ +function urlIsSameOrigin(requestUrl) { +  var parsed = (isString(requestUrl)) ? urlResolve(requestUrl) : requestUrl; +  return (parsed.protocol === originUrl.protocol && +          parsed.host === originUrl.host);  } | 
