]> 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:47:23 +0000 (15:47 -0500)
Fixes gh-1875
Closes gh-1880
(cherry picked from commit 5a75278e4c5359e07303fc4d8e78a1cf94f6ad65)

Conflicts:
src/ajax.js

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

index d4a0128b46aa04b3a955d4c51333be75b059caac..d8450e1c3e159379579bd65577b867aba462e40a 100644 (file)
@@ -12,12 +12,11 @@ define([
 var
        rhash = /#.*$/,
        rts = /([?&])_=[^&]*/,
-       rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+       rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
        // #7653, #8125, #8152: local protocol detection
        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,10 @@ var
        // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
        allTypes = "*/".concat( "*" ),
 
-       // Document location
-       ajaxLocation = location.href,
+       // Anchor tag for parsing the document origin
+       originAnchor = document.createElement( "a" );
 
-       // Segment location into parts
-       ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+       originAnchor.href = location.href;
 
 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
 function addToPrefiltersOrTransports( structure ) {
@@ -287,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,
@@ -381,8 +379,7 @@ jQuery.extend({
                // Force options to be an object
                options = options || {};
 
-               var // Cross-domain detection vars
-                       parts,
+               var
                        // Loop variable
                        i,
                        // URL without anti-cache param
@@ -391,7 +388,8 @@ jQuery.extend({
                        responseHeadersString,
                        // timeout handle
                        timeoutTimer,
-
+                       // Url cleanup var
+                       urlAnchor,
                        // To know if global events are to be dispatched
                        fireGlobals,
 
@@ -498,9 +496,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;
@@ -508,14 +505,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 da1f6ecb9b41d35dbb063878e9d7156eed3d6b62..7a5ab344534a4533974cc255dd34fcbe904ac612 100644 (file)
@@ -296,7 +296,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",
@@ -346,6 +346,10 @@ module( "ajax", {
                                {
                                        crossDomain: true
                                }
+                       ),
+                       request(
+                               " http://otherdomain.com",
+                               "Cross-domain url with leading space is detected as cross-domain"
                        )
                ];
        });