From: Ben Toews Date: Sun, 23 Nov 2014 01:29:13 +0000 (-0700) Subject: Ajax: use anchor tag for parsing urls X-Git-Tag: 3.0.0-alpha1+compat~176 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=de7ae8cd17a22b0275217a6ca0345d9d5a97c6dd;p=jquery.git Ajax: use anchor tag for parsing urls Fixes gh-1875 Closes gh-1880 (cherry picked from commit 5a75278e4c5359e07303fc4d8e78a1cf94f6ad65) Conflicts: src/ajax.js --- diff --git a/src/ajax.js b/src/ajax.js index d4a0128b4..d8450e1c3 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -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 diff --git a/test/unit/ajax.js b/test/unit/ajax.js index da1f6ecb9..7a5ab3445 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -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" ) ]; });