]> source.dussan.org Git - jquery.git/commitdiff
Ajax: Do not execute scripts for unsuccessful HTTP responses
authorSean Robinson <sean.robinson@scottsdalecc.edu>
Fri, 26 Apr 2019 14:25:08 +0000 (07:25 -0700)
committerMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 6 Apr 2020 20:33:56 +0000 (22:33 +0200)
The script transport used to evaluate fetched script sources which is
undesirable for unsuccessful HTTP responses. This is different to other data
types where such a convention was fine (e.g. in case of JSON).

(cherry picked from 50871a5a85cc802421b40cc67e2830601968affe)

Fixes gh-4250
Fixes gh-4655
Closes gh-4379

src/ajax.js
test/data/mock.php
test/middleware-mockserver.js
test/unit/ajax.js

index 7e8f552aacd14043f21bb3de10b598084853fdd1..d1bebd540e2acf40a6e8e60fa3b3e63da90bbc0e 100644 (file)
@@ -744,6 +744,11 @@ jQuery.extend( {
                                response = ajaxHandleResponses( s, jqXHR, responses );
                        }
 
+                       // Use a noop converter for missing script
+                       if ( !isSuccess && jQuery.inArray( "script", s.dataTypes ) > -1 ) {
+                               s.converters[ "text script" ] = function() {};
+                       }
+
                        // Convert no matter what (that way responseXXX fields are always set)
                        response = ajaxConvert( s, response, jqXHR, isSuccess );
 
index ba1930415383485c03351b1d8837ce1b65d69652..5b56d02c7e0740caf5c4535e1c1a6e1c2cd5ecb5 100644 (file)
@@ -216,6 +216,19 @@ QUnit.assert.ok( true, "mock executed");';
                unlink( $this->cspFile );
        }
 
+       protected function errorWithScript( $req ) {
+               header( 'HTTP/1.0 404 Not Found' );
+               if ( isset( $req->query['withScriptContentType'] ) ) {
+                       header( 'Content-Type: application/javascript' );
+               }
+               if ( isset( $req->query['callback'] ) ) {
+                       $callback = $req->query['callback'];
+                       echo $callback . '( {"status": 404, "msg": "Not Found"} )';
+               } else {
+                       echo 'QUnit.assert.ok( false, "Mock return erroneously executed" );';
+               }
+       }
+
        public function __construct() {
                $this->cspFile = __DIR__ . '/support/csp.log';
        }
index 20a660714007ed6adf14880fe8fe56447b3fce4c..bddfafc94f9a43218b5da562743f7a291c88f51d 100644 (file)
@@ -226,6 +226,18 @@ var mocks = {
                cspLog = "";
                resp.writeHead( 200 );
                resp.end();
+       },
+       errorWithScript: function( req, resp ) {
+               if ( req.query.withScriptContentType ) {
+                       resp.writeHead( 404, { "Content-Type": "application/javascript" } );
+               } else {
+                       resp.writeHead( 404 );
+               }
+               if ( req.query.callback ) {
+                       resp.end( req.query.callback + "( {\"status\": 404, \"msg\": \"Not Found\"} )" );
+               } else {
+                       resp.end( "QUnit.assert.ok( false, \"Mock return erroneously executed\" );" );
+               }
        }
 };
 var handlers = {
index d9b984799cf5ed80fd6deb9ee7a1869d8181a25d..8b3850605ebe48324fce8c0c48b305c2fd9e8cc8 100644 (file)
@@ -837,6 +837,121 @@ QUnit.module( "ajax", {
                };
        } );
 
+       ajaxTest( "jQuery.ajax() - do not execute scripts from unsuccessful responses (gh-4250)", 11, function( assert ) {
+               var globalEval = jQuery.globalEval;
+
+               var failConverters = {
+                       "text script": function() {
+                               assert.ok( false, "No converter for unsuccessful response" );
+                       }
+               };
+
+               function request( title, options ) {
+                       var testMsg = title + ": expected file missing status";
+                       return jQuery.extend( {
+                               beforeSend: function() {
+                                       jQuery.globalEval = function() {
+                                               assert.ok( false, "Should not eval" );
+                                       };
+                               },
+                               complete: function() {
+                                       jQuery.globalEval = globalEval;
+                               },
+                               // error is the significant assertion
+                               error: function( xhr ) {
+                                       assert.strictEqual( xhr.status, 404, testMsg );
+                               },
+                               success: function() {
+                                       assert.ok( false, "Unanticipated success" );
+                               }
+                       }, options );
+               }
+
+               return [
+                       request(
+                               "HTML reply",
+                               {
+                                       url: url( "404.txt" )
+                               }
+                       ),
+                       request(
+                               "HTML reply with dataType",
+                               {
+                                       dataType: "script",
+                                       url: url( "404.txt" )
+                               }
+                       ),
+                       request(
+                               "script reply",
+                               {
+                                       url: url( "mock.php?action=errorWithScript&withScriptContentType" )
+                               }
+                       ),
+                       request(
+                               "non-script reply",
+                               {
+                                       url: url( "mock.php?action=errorWithScript" )
+                               }
+                       ),
+                       request(
+                               "script reply with dataType",
+                               {
+                                       dataType: "script",
+                                       url: url( "mock.php?action=errorWithScript&withScriptContentType" )
+                               }
+                       ),
+                       request(
+                               "non-script reply with dataType",
+                               {
+                                       dataType: "script",
+                                       url: url( "mock.php?action=errorWithScript" )
+                               }
+                       ),
+                       request(
+                               "script reply with converter",
+                               {
+                                       converters: failConverters,
+                                       url: url( "mock.php?action=errorWithScript&withScriptContentType" )
+                               }
+                       ),
+                       request(
+                               "non-script reply with converter",
+                               {
+                                       converters: failConverters,
+                                       url: url( "mock.php?action=errorWithScript" )
+                               }
+                       ),
+                       request(
+                               "script reply with converter and dataType",
+                               {
+                                       converters: failConverters,
+                                       dataType: "script",
+                                       url: url( "mock.php?action=errorWithScript&withScriptContentType" )
+                               }
+                       ),
+                       request(
+                               "non-script reply with converter and dataType",
+                               {
+                                       converters: failConverters,
+                                       dataType: "script",
+                                       url: url( "mock.php?action=errorWithScript" )
+                               }
+                       ),
+                       request(
+                               "JSONP reply with dataType",
+                               {
+                                       dataType: "jsonp",
+                                       url: url( "mock.php?action=errorWithScript" ),
+                                       beforeSend: function() {
+                                               jQuery.globalEval = function( response ) {
+                                                       assert.ok( /"status": 404, "msg": "Not Found"/.test( response ), "Error object returned" );
+                                               };
+                                       }
+                               }
+                       )
+               ];
+       } );
+
        ajaxTest( "jQuery.ajax() - synchronous request", 1, function( assert ) {
                return {
                        url: url( "json_obj.js" ),