]> source.dussan.org Git - jquery.git/commitdiff
Ajax: use anchor tag for parsing urls
authorBen Toews <mastahyeti@gmail.com>
Sun, 23 Nov 2014 01:29:13 +0000 (18:29 -0700)
committerDave Methvin <dave.methvin@gmail.com>
Thu, 11 Dec 2014 20:26:04 +0000 (15:26 -0500)
Fixes gh-1875
Closes gh-1880

src/ajax.js
test/unit/ajax.js

index dad2f8282590ccad3c6bd40460ec53a41f981083..9765e95d61ea73eb453ae0093ebec17859f627ec 100644 (file)
@@ -17,7 +17,6 @@ var
        rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
        rnoContent = /^(?:GET|HEAD)$/,
        rprotocol = /^\/\//,
-       rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
 
        /* Prefilters
         * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
@@ -40,11 +39,9 @@ var
        // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
        allTypes = "*/".concat( "*" ),
 
-       // Document location
-       ajaxLocation = location.href,
-
-       // Segment location into parts
-       ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+       // Anchor tag for parsing the document origin
+       originAnchor = document.createElement( "a" );
+       originAnchor.href = location.href;
 
 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
 function addToPrefiltersOrTransports( structure ) {
@@ -288,9 +285,9 @@ jQuery.extend({
        etag: {},
 
        ajaxSettings: {
-               url: ajaxLocation,
+               url: location.href,
                type: "GET",
-               isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+               isLocal: rlocalProtocol.test( location.protocol ),
                global: true,
                processData: true,
                async: true,
@@ -390,8 +387,8 @@ jQuery.extend({
                        responseHeaders,
                        // timeout handle
                        timeoutTimer,
-                       // Cross-domain detection vars
-                       parts,
+                       // Url cleanup var
+                       urlAnchor,
                        // To know if global events are to be dispatched
                        fireGlobals,
                        // Loop variable
@@ -496,8 +493,8 @@ jQuery.extend({
                // Add protocol if not provided (prefilters might expect it)
                // Handle falsy url in the settings object (#10093: consistency with old signature)
                // We also use the url parameter if available
-               s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
-                       .replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+               s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
+                       .replace( rprotocol, location.protocol + "//" );
 
                // Alias method option to type as per ticket #12004
                s.type = options.method || options.type || s.method || s.type;
@@ -505,14 +502,24 @@ jQuery.extend({
                // Extract dataTypes list
                s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
 
-               // A cross-domain request is in order when we have a protocol:host:port mismatch
+               // A cross-domain request is in order when the origin doesn't match the current origin.
                if ( s.crossDomain == null ) {
-                       parts = rurl.exec( s.url.toLowerCase() );
-                       s.crossDomain = !!( parts &&
-                               ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
-                                       ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
-                                               ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
-                       );
+                       urlAnchor = document.createElement( "a" );
+
+                       // Support: IE8-11+
+                       // IE throws exception if url is malformed, e.g. http://example.com:80x/
+                       try {
+                               urlAnchor.href = s.url;
+                               // Support: IE8-11+
+                               // Anchor's host property isn't correctly set when s.url is relative
+                               urlAnchor.href = urlAnchor.href;
+                               s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+                                       urlAnchor.protocol + "//" + urlAnchor.host;
+                       } catch ( e ) {
+                               // If there is an error parsing the URL, assume it is crossDomain,
+                               // it can be rejected by the transport if it is invalid
+                               s.crossDomain = true;
+                       }
                }
 
                // Convert data if not already a string
index 6f3bacebe2ddfc945e6c2cf0da2cf97f3149b88b..468d3845982bf15b62131a28e7814a6f5e27f208 100644 (file)
@@ -301,7 +301,7 @@ module( "ajax", {
                }
        ]);
 
-       ajaxTest( "jQuery.ajax() - cross-domain detection", 7, function() {
+       ajaxTest( "jQuery.ajax() - cross-domain detection", 8, function() {
                function request( url, title, crossDomainOrOptions ) {
                        return jQuery.extend( {
                                dataType: "jsonp",
@@ -351,6 +351,10 @@ module( "ajax", {
                                {
                                        crossDomain: true
                                }
+                       ),
+                       request(
+                               " http://otherdomain.com",
+                               "Cross-domain url with leading space is detected as cross-domain"
                        )
                ];
        });