aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.json1
-rw-r--r--src/ajax.js6
-rw-r--r--src/ajax/binary.js17
-rw-r--r--src/jquery.js1
-rw-r--r--test/data/mock.php11
-rw-r--r--test/data/testinit.js7
-rw-r--r--test/middleware-mockserver.js28
-rw-r--r--test/unit/ajax.js43
8 files changed, 109 insertions, 5 deletions
diff --git a/package.json b/package.json
index 3afa4e5f1..153eb8d6a 100644
--- a/package.json
+++ b/package.json
@@ -55,6 +55,7 @@
"karma-qunit": "4.1.2",
"karma-webkit-launcher": "2.1.0",
"load-grunt-tasks": "5.1.0",
+ "multiparty": "4.2.3",
"native-promise-only": "0.8.1",
"playwright-webkit": "1.29.2",
"promises-aplus-tests": "2.1.2",
diff --git a/src/ajax.js b/src/ajax.js
index 36a9c9b57..db4e30195 100644
--- a/src/ajax.js
+++ b/src/ajax.js
@@ -562,14 +562,14 @@ jQuery.extend( {
}
}
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
// Convert data if not already a string
if ( s.data && s.processData && typeof s.data !== "string" ) {
s.data = jQuery.param( s.data, s.traditional );
}
- // Apply prefilters
- inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
-
// If request was aborted inside a prefilter, stop there
if ( completed ) {
return jqXHR;
diff --git a/src/ajax/binary.js b/src/ajax/binary.js
new file mode 100644
index 000000000..e96661da7
--- /dev/null
+++ b/src/ajax/binary.js
@@ -0,0 +1,17 @@
+import jQuery from "../core.js";
+
+import "../ajax.js";
+
+jQuery.ajaxPrefilter( function( s ) {
+
+ // Binary data needs to be passed to XHR as-is without stringification.
+ if ( typeof s.data !== "string" && !jQuery.isPlainObject( s.data ) ) {
+ s.processData = false;
+ }
+
+ // `Content-Type` for requests with `FormData` bodies needs to be set
+ // by the browser as it needs to append the `boundary` it generated.
+ if ( s.data instanceof window.FormData ) {
+ s.contentType = false;
+ }
+} );
diff --git a/src/jquery.js b/src/jquery.js
index a0d5d3647..d833516d4 100644
--- a/src/jquery.js
+++ b/src/jquery.js
@@ -23,6 +23,7 @@ import "./ajax.js";
import "./ajax/xhr.js";
import "./ajax/script.js";
import "./ajax/jsonp.js";
+import "./ajax/binary.js";
import "./ajax/load.js";
import "./core/parseXML.js";
import "./core/parseHTML.js";
diff --git a/test/data/mock.php b/test/data/mock.php
index 0cb88cf47..1955f56fc 100644
--- a/test/data/mock.php
+++ b/test/data/mock.php
@@ -124,6 +124,17 @@ QUnit.assert.ok( true, "mock executed");';
echo "$cleanCallback($text)\n";
}
+ protected function formData( $req ) {
+ $prefix = 'multipart/form-data; boundary=--';
+ $contentTypeValue = $req->headers[ 'CONTENT-TYPE' ];
+ if ( substr( $contentTypeValue, 0, strlen( $prefix ) ) === $prefix ) {
+ echo 'key1 -> ' . $_POST[ 'key1' ] . ', key2 -> ' . $_POST[ 'key2' ];
+ } else {
+ echo 'Incorrect Content-Type: ' . $contentTypeValue .
+ "\nExpected prefix: " . $prefix;
+ }
+ }
+
protected function error( $req ) {
header( 'HTTP/1.0 400 Bad Request' );
if ( isset( $req->query['json'] ) ) {
diff --git a/test/data/testinit.js b/test/data/testinit.js
index 6503b70a5..906686d86 100644
--- a/test/data/testinit.js
+++ b/test/data/testinit.js
@@ -174,8 +174,11 @@ function url( value ) {
}
// Ajax testing helper
-this.ajaxTest = function( title, expect, options ) {
- QUnit.test( title, function( assert ) {
+this.ajaxTest = function( title, expect, options, wrapper ) {
+ if ( !wrapper ) {
+ wrapper = QUnit.test;
+ }
+ wrapper.call( QUnit, title, function( assert ) {
assert.expect( expect );
var requestOptions;
diff --git a/test/middleware-mockserver.js b/test/middleware-mockserver.js
index 2b6970226..35e4c1778 100644
--- a/test/middleware-mockserver.js
+++ b/test/middleware-mockserver.js
@@ -3,6 +3,7 @@
const url = require( "url" );
const fs = require( "fs" );
const getRawBody = require( "raw-body" );
+const multiparty = require( "multiparty" );
let cspLog = "";
@@ -141,6 +142,19 @@ const mocks = {
resp.writeHead( 200 );
resp.end( `${ cleanCallback( callback ) }(${ JSON.stringify( body ) })\n` );
},
+ formData: function( req, resp, next ) {
+ const prefix = "multipart/form-data; boundary=--";
+ const contentTypeValue = req.headers[ "content-type" ];
+ resp.writeHead( 200 );
+ if ( ( prefix || "" ).startsWith( prefix ) ) {
+ getMultiPartContent( req ).then( function( { fields = {} } ) {
+ resp.end( `key1 -> ${ fields.key1 }, key2 -> ${ fields.key2 }` );
+ }, next );
+ } else {
+ resp.end( `Incorrect Content-Type: ${ contentTypeValue
+ }\nExpected prefix: ${ prefix }` );
+ }
+ },
error: function( req, resp ) {
if ( req.query.json ) {
resp.writeHead( 400, { "content-type": "application/json" } );
@@ -363,4 +377,18 @@ function getBody( req ) {
} );
}
+function getMultiPartContent( req ) {
+ return new Promise( function( resolve ) {
+ if ( req.method !== "POST" ) {
+ resolve( "" );
+ return;
+ }
+
+ const form = new multiparty.Form();
+ form.parse( req, function( _err, fields, files ) {
+ resolve( { fields, files } );
+ } );
+ } );
+}
+
module.exports = MockserverMiddlewareFactory;
diff --git a/test/unit/ajax.js b/test/unit/ajax.js
index fec1d9565..7ecedc212 100644
--- a/test/unit/ajax.js
+++ b/test/unit/ajax.js
@@ -3105,4 +3105,47 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
assert.ok( jQuery.active === 0, "ajax active counter should be zero: " + jQuery.active );
} );
+ ajaxTest( "jQuery.ajax() - FormData", 1, function( assert ) {
+ var formData = new FormData();
+ formData.append( "key1", "value1" );
+ formData.append( "key2", "value2" );
+
+ return {
+ url: url( "mock.php?action=formData" ),
+ method: "post",
+ data: formData,
+ success: function( data ) {
+ assert.strictEqual( data, "key1 -> value1, key2 -> value2",
+ "FormData sent correctly" );
+ }
+ };
+ } );
+
+ ajaxTest( "jQuery.ajax() - URLSearchParams", 1, function( assert ) {
+ var urlSearchParams = new URLSearchParams();
+ urlSearchParams.append( "name", "peter" );
+
+ return {
+ url: url( "mock.php?action=name" ),
+ method: "post",
+ data: urlSearchParams,
+ success: function( data ) {
+ assert.strictEqual( data, "pan", "URLSearchParams sent correctly" );
+ }
+ };
+ }, QUnit.testUnlessIE );
+
+ ajaxTest( "jQuery.ajax() - Blob", 1, function( assert ) {
+ var blob = new Blob( [ "name=peter" ], { type: "text/plain" } );
+
+ return {
+ url: url( "mock.php?action=name" ),
+ method: "post",
+ data: blob,
+ success: function( data ) {
+ assert.strictEqual( data, "pan", "Blob sent correctly" );
+ }
+ };
+ } );
+
} )();