diff --git a/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java b/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java index 011b0dc..5617508 100644 --- a/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java +++ b/src/android/com/silkimen/cordovahttp/CordovaHttpBase.java @@ -1,7 +1,9 @@ package com.silkimen.cordovahttp; -import java.io.IOException; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; @@ -19,9 +21,11 @@ import com.silkimen.http.TLSConfiguration; import org.apache.cordova.CallbackContext; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import android.util.Base64; import android.util.Log; abstract class CordovaHttpBase implements Runnable { @@ -120,7 +124,7 @@ abstract class CordovaHttpBase implements Runnable { request.readTimeout(this.timeout); request.acceptCharset("UTF-8"); request.uncompress(true); - request.setConnectionFactory(new OkConnectionFactory()); + HttpRequest.setConnectionFactory(new OkConnectionFactory()); if (this.tlsConfiguration.getHostnameVerifier() != null) { request.setHostnameVerifier(this.tlsConfiguration.getHostnameVerifier()); @@ -141,6 +145,8 @@ abstract class CordovaHttpBase implements Runnable { request.contentType("text/plain", "UTF-8"); } else if ("urlencoded".equals(this.serializer)) { // intentionally left blank, because content type is set in HttpRequest.form() + } else if ("multipart".equals(this.serializer)) { + request.contentType("multipart/form-data"); } } @@ -155,6 +161,22 @@ abstract class CordovaHttpBase implements Runnable { request.send(((JSONObject) this.data).getString("text")); } else if ("urlencoded".equals(this.serializer)) { request.form(JsonUtils.getObjectMap((JSONObject) this.data)); + } else if ("multipart".equals(this.serializer)) { + JSONArray buffers = ((JSONObject) this.data).getJSONArray("buffers"); + JSONArray names = ((JSONObject) this.data).getJSONArray("names"); + JSONArray fileNames = ((JSONObject) this.data).getJSONArray("fileNames"); + JSONArray types = ((JSONObject) this.data).getJSONArray("types"); + + for (int i = 0; i < buffers.length(); ++i) { + byte[] bytes = Base64.decode(buffers.getString(i), Base64.DEFAULT); + String name = names.getString(i); + + if (fileNames.isNull(i)) { + request.part(name, new String(bytes, "UTF-8")); + } else { + request.part(name, fileNames.getString(i), types.getString(i), new ByteArrayInputStream(bytes)); + } + } } } diff --git a/test/e2e-specs.js b/test/e2e-specs.js index 082a2b4..36047fd 100644 --- a/test/e2e-specs.js +++ b/test/e2e-specs.js @@ -33,6 +33,7 @@ const helpers = { setJsonSerializer: function (resolve) { resolve(cordova.plugin.http.setDataSerializer('json')); }, setUtf8StringSerializer: function (resolve) { resolve(cordova.plugin.http.setDataSerializer('utf8')); }, setUrlEncodedSerializer: function (resolve) { resolve(cordova.plugin.http.setDataSerializer('urlencoded')); }, + setMultipartSerializer: function (resolve) { resolve(cordova.plugin.http.setDataSerializer('multipart')); }, disableFollowingRedirect: function (resolve) { resolve(cordova.plugin.http.setFollowRedirect(false)); }, enableFollowingRedirect: function(resolve) { resolve(cordova.plugin.http.setFollowRedirect(true)); }, getWithXhr: function (done, url, type) { @@ -789,8 +790,29 @@ const tests = [ result.data.status.should.be.equal(418); result.data.error.should.be.equal("\n -=[ teapot ]=-\n\n _...._\n .' _ _ `.\n | .\"` ^ `\". _,\n \\_;`\"---\"`|//\n | ;/\n \\_ _/\n `\"\"\"`\n"); } - } - // @TODO: not ready yet + }, + + // TODO: not ready yet + // { + // description: 'should serialize FormData instance correctly when it contains string value', + // expected: 'resolved: {"status": 200, ...', + // before: helpers.setMultipartSerializer, + // func: function (resolve, reject) { + // var formData = new FormData(); + // formData.append('myString', 'This is a test!'); + + // var url = 'https://httpbin.org/anything'; + // var options = { method: 'post', data: formData }; + // cordova.plugin.http.sendRequest(url, options, resolve, reject); + // }, + // validationFunc: function (driver, result) { + // console.log(result.data); + // result.type.should.be.equal('resolved'); + // result.data.status.should.be.equal(200); + // } + // } + + // TODO: not ready yet // { // description: 'should authenticate correctly when client cert auth is configured with a PKCS12 container', // expected: 'resolved: {"status": 200, ...', diff --git a/test/js-specs.js b/test/js-specs.js index 6ba07ee..c7f0d5f 100644 --- a/test/js-specs.js +++ b/test/js-specs.js @@ -1,8 +1,11 @@ const chai = require('chai'); const mock = require('mock-require'); +const util = require('util'); const should = chai.should(); +const BlobMock = require('./mocks/Blob.mock'); const ConsoleMock = require('./mocks/Console.mock'); +const FileReaderMock = require('./mocks/FileReader.mock'); const FormDataMock = require('./mocks/FormData.mock'); describe('Advanced HTTP public interface', function () { @@ -32,7 +35,7 @@ describe('Advanced HTTP public interface', function () { beforeEach(() => { // mocked btoa function (base 64 encoding strings) - global.btoa = decoded => new Buffer(decoded).toString('base64'); + global.btoa = decoded => Buffer.from(decoded).toString('base64'); loadHttp(getDependenciesBlueprint()); }); @@ -512,33 +515,82 @@ describe('Common helpers', function () { }); }); - describe('getProcessedData()', function () { + describe('processData()', function () { + const mockWindow = { + Blob: BlobMock, + FileReader: FileReaderMock, + FormData: FormDataMock, + TextEncoder: util.TextEncoder, + } + + const base64 = { fromArrayBuffer: ab => Buffer.from(ab).toString('base64') }; const jsUtil = require('../www/js-util'); const messages = require('../www/messages'); - const dependencyValidator = require('../www/dependency-validator')(FormDataMock, null, messages); - const helpers = require('../www/helpers')({ FormData: FormDataMock }, jsUtil, null, messages, null, null, dependencyValidator); + const dependencyValidator = require('../www/dependency-validator')(mockWindow, null, messages); + const helpers = require('../www/helpers')(mockWindow, jsUtil, null, messages, base64, null, dependencyValidator); + + const testString = 'Test String öäüß 👍😉'; + const testStringBase64 = Buffer.from(testString).toString('base64'); it('throws an error when given data does not match allowed data types', () => { - (() => helpers.getProcessedData('myString', 'urlencoded')).should.throw(messages.TYPE_MISMATCH_DATA); - (() => helpers.getProcessedData('myString', 'json')).should.throw(messages.TYPE_MISMATCH_DATA); - (() => helpers.getProcessedData({}, 'utf8')).should.throw(messages.TYPE_MISMATCH_DATA); + (() => helpers.processData('myString', 'urlencoded')).should.throw(messages.TYPE_MISMATCH_DATA); + (() => helpers.processData('myString', 'json')).should.throw(messages.TYPE_MISMATCH_DATA); + (() => helpers.processData({}, 'utf8')).should.throw(messages.TYPE_MISMATCH_DATA); }); it('throws an error when needed Web API is not available', () => { const helpers = require('../www/helpers')({}, jsUtil, null, messages, null, null); - (() => helpers.getProcessedData(null, 'multipart')).should.throw(`${messages.INSTANCE_TYPE_NOT_SUPPORTED} FormData`); + (() => helpers.processData(null, 'multipart')).should.throw(`${messages.INSTANCE_TYPE_NOT_SUPPORTED} FormData`); }); it('throws an error when given data does not match allowed instance types', () => { - (() => helpers.getProcessedData('myString', 'multipart')).should.throw(messages.INSTANCE_TYPE_MISMATCH_DATA); + (() => helpers.processData('myString', 'multipart')).should.throw(messages.INSTANCE_TYPE_MISMATCH_DATA); }); - it('processes data correctly when serializer "utf8" is configured', () => { - helpers.getProcessedData('myString', 'utf8').should.be.eql({text: 'myString'}); + it('processes data correctly when serializer "utf8" is configured', (cb) => { + helpers.processData('myString', 'utf8', (data) => { + data.should.be.eql({text: 'myString'}); + cb(); + }) }); - it('processes data correctly when serializer "multipart" is configured', () => { - helpers.getProcessedData(new FormDataMock(), 'multipart'); + it('processes data correctly when serializer "multipart" is configured and form data contains string value', (cb) => { + const formData = new FormDataMock(); + formData.append('myString', testString); + + helpers.processData(formData, 'multipart', (data) => { + data.buffers.length.should.be.equal(1); + data.names.length.should.be.equal(1); + data.fileNames.length.should.be.equal(1); + data.types.length.should.be.equal(1); + + data.buffers[0].should.be.eql(testStringBase64); + data.names[0].should.be.equal('myString'); + should.equal(data.fileNames[0], null); + data.types[0].should.be.equal('text/plain'); + + + cb(); + }); + }); + + it('processes data correctly when serializer "multipart" is configured and form data contains file value', (cb) => { + const formData = new FormDataMock(); + formData.append('myFile', new BlobMock([testString], { type: 'application/octet-stream' })); + + helpers.processData(formData, 'multipart', (data) => { + data.buffers.length.should.be.equal(1); + data.names.length.should.be.equal(1); + data.fileNames.length.should.be.equal(1); + data.types.length.should.be.equal(1); + + data.buffers[0].should.be.eql(testStringBase64); + data.names[0].should.be.equal('myFile'); + data.fileNames[0].should.be.equal('blob'); + data.types[0].should.be.equal('application/octet-stream'); + + cb(); + }); }); }); }); @@ -550,7 +602,7 @@ describe('Dependency Validator', function () { it('logs a warning message if FormData API is not supported', function () { const console = new ConsoleMock(); - require('../www/dependency-validator')(undefined, console, messages).logWarnings(); + require('../www/dependency-validator')({}, console, messages).logWarnings(); console.messageList.length.should.be.equal(1); console.messageList[0].type.should.be.equal('warn'); @@ -560,7 +612,7 @@ describe('Dependency Validator', function () { it('logs a warning message if FormData.entries() API is not supported', function () { const console = new ConsoleMock(); - require('../www/dependency-validator')({}, console, messages).logWarnings(); + require('../www/dependency-validator')({ FormData: {} }, console, messages).logWarnings(); console.messageList.length.should.be.equal(1); console.messageList[0].type.should.be.equal('warn'); @@ -568,9 +620,39 @@ describe('Dependency Validator', function () { }); }); + describe('checkBlobApi()', function () { + it('throws an error if Blob API is not supported', function () { + const console = new ConsoleMock(); + const validator = require('../www/dependency-validator')({}, console, messages); + + (() => validator.checkBlobApi()).should.throw(messages.MISSING_BLOB_API); + }); + }); + + describe('checkFileReaderApi()', function () { + it('throws an error if FileReader API is not supported', function () { + const console = new ConsoleMock(); + const validator = require('../www/dependency-validator')({}, console, messages); + + (() => validator.checkFileReaderApi()).should.throw(messages.MISSING_FILE_READER_API); + }); + }); + describe('checkFormDataApi()', function () { it('throws an error if FormData.entries() API is not supported', function () { - (() => require('../www/dependency-validator')(null, null, messages).checkFormDataApi()).should.throw(messages.MISSING_FORMDATA_ENTRIES_API); + const console = new ConsoleMock(); + const validator = require('../www/dependency-validator')({ FormData: {}}, console, messages); + + (() => validator.checkFormDataApi()).should.throw(messages.MISSING_FORMDATA_ENTRIES_API); + }); + }); + + describe('checkTextEncoderApi()', function () { + it('throws an error if TextEncoder API is not supported', function () { + const console = new ConsoleMock(); + const validator = require('../www/dependency-validator')({}, console, messages); + + (() => validator.checkTextEncoderApi()).should.throw(messages.MISSING_TEXT_ENCODER_API); }); }); }); diff --git a/test/mocks/Blob.mock.js b/test/mocks/Blob.mock.js new file mode 100644 index 0000000..619d542 --- /dev/null +++ b/test/mocks/Blob.mock.js @@ -0,0 +1,35 @@ +module.exports = class BlobMock { + constructor(blobParts, options) { + if (blobParts instanceof BlobMock) { + this._buffer = blobParts._buffer; + } else { + this._buffer = new Uint8Array(Buffer.concat(blobParts.map(part => Buffer.from(part, 'utf8')))).buffer; + } + + this._type = options.type || ''; + } + + get size() { + return this._buffer.length; + } + + get type() { + return this._type; + } + + arrayBuffer() { + throw new Error('Not implemented in BlobMock.'); + } + + slice() { + throw new Error('Not implemented in BlobMock.'); + } + + stream() { + throw new Error('Not implemented in BlobMock.'); + } + + text() { + throw new Error('Not implemented in BlobMock.'); + } +} diff --git a/test/mocks/File.mock.js b/test/mocks/File.mock.js new file mode 100644 index 0000000..1c1ccfc --- /dev/null +++ b/test/mocks/File.mock.js @@ -0,0 +1,12 @@ +const BlobMock = require('./Blob.mock'); + +module.exports = class FileMock extends BlobMock { + constructor(blob, fileName) { + super(blob, { type: blob.type }); + this._fileName = fileName || ''; + } + + get name() { + return this._fileName; + } +} diff --git a/test/mocks/FileReader.mock.js b/test/mocks/FileReader.mock.js new file mode 100644 index 0000000..7ae6172 --- /dev/null +++ b/test/mocks/FileReader.mock.js @@ -0,0 +1,39 @@ +module.exports = class FileReaderMock { + constructor() { + this.EMPTY = 0; + this.LOADING = 1; + this.DONE = 2; + + this.error = null; + this.onabort = () => {}; + this.onerror = () => {}; + this.onload = () => {}; + this.onloadend = () => {}; + this.onloadstart = () => {}; + this.onprogress = () => {}; + this.readyState = this.EMPTY; + this.result = null; + } + + readAsArrayBuffer(file) { + this.readyState = this.LOADING; + this.onloadstart(); + this.onprogress(); + this.result = file._buffer; + this.readyState = this.DONE; + this.onloadend(); + this.onload(); + } + + readAsBinaryString() { + throw new Error('Not implemented in FileReaderMock.'); + } + + readAsDataUrl() { + throw new Error('Not implemented in FileReaderMock.'); + } + + readAsText() { + throw new Error('Not implemented in FileReaderMock.'); + } +} diff --git a/test/mocks/FormData.mock.js b/test/mocks/FormData.mock.js index 186c3c7..4419c33 100644 --- a/test/mocks/FormData.mock.js +++ b/test/mocks/FormData.mock.js @@ -1,6 +1,17 @@ +const BlobMock = require('./Blob.mock'); +const FileMock = require('./File.mock'); + module.exports = class FormDataMock { - append() { - throw new Error('Not implemented in FormDataMock.'); + constructor() { + this.map = new Map(); + } + + append(name, value, filename) { + if (value instanceof BlobMock) { + this.map.set(name, new FileMock(value, filename)) + } else { + this.map.set(name, value); + } } delete() { @@ -8,34 +19,34 @@ module.exports = class FormDataMock { } entries() { - throw new Error('Not implemented in FormDataMock.'); + return this.map.entries(); } - forEach() { - throw new Error('Not implemented in FormDataMock.'); + forEach(cb) { + return this.map.forEach(cb); } - get() { - throw new Error('Not implemented in FormDataMock.'); + get(key) { + return this.map.get(key); } getAll() { throw new Error('Not implemented in FormDataMock.'); } - has() { - throw new Error('Not implemented in FormDataMock.'); + has(key) { + return this.map.has(key); } keys() { - throw new Error('Not implemented in FormDataMock.'); + return this.map.keys(); } - set() { - throw new Error('Not implemented in FormDataMock.'); + set(key, value) { + return this.map.set(key, value); } values() { - throw new Error('Not implemented in FormDataMock.'); + return this.map.values(); } }; diff --git a/www/advanced-http.js b/www/advanced-http.js index a5174a8..54f90c0 100644 --- a/www/advanced-http.js +++ b/www/advanced-http.js @@ -14,7 +14,7 @@ var ToughCookie = require(pluginId + '.tough-cookie'); var lodash = require(pluginId + '.lodash'); var WebStorageCookieStore = require(pluginId + '.local-storage-store')(ToughCookie, lodash); var cookieHandler = require(pluginId + '.cookie-handler')(window.localStorage, ToughCookie, WebStorageCookieStore); -var dependencyValidator = require(pluginId + '.dependency-validator')(window.FormData, window.console, messages); +var dependencyValidator = require(pluginId + '.dependency-validator')(window, window.console, messages); var helpers = require(pluginId + '.helpers')(window, jsUtil, cookieHandler, messages, base64, errorCodes, dependencyValidator); var urlUtil = require(pluginId + '.url-util')(jsUtil); var publicInterface = require(pluginId + '.public-interface')(exec, cookieHandler, urlUtil, helpers, globalConfigs, errorCodes); diff --git a/www/dependency-validator.js b/www/dependency-validator.js index 2b56c0b..9858a07 100644 --- a/www/dependency-validator.js +++ b/www/dependency-validator.js @@ -1,22 +1,43 @@ -module.exports = function init(FormData, console, messages) { +module.exports = function init(global, console, messages) { var interface = { + checkBlobApi: checkBlobApi, + checkFileReaderApi: checkFileReaderApi, checkFormDataApi: checkFormDataApi, + checkTextEncoderApi: checkTextEncoderApi, logWarnings: logWarnings, }; return interface; function logWarnings() { - if (!FormData) { + if (!global.FormData) { console.warn(messages.MISSING_FORMDATA_API); - } else if (!FormData.prototype || !FormData.prototype.entries) { + } else if (!global.FormData.prototype || !global.FormData.prototype.entries) { console.warn(messages.MISSING_FORMDATA_ENTRIES_API); } } + function checkBlobApi() { + if (!global.Blob || !global.Blob.prototype) { + throw new Error(messages.MISSING_BLOB_API); + } + } + + function checkFileReaderApi() { + if (!global.FileReader || !global.FileReader.prototype) { + throw new Error(messages.MISSING_FILE_READER_API); + } + } + function checkFormDataApi() { - if (!FormData || !FormData.prototype || !FormData.prototype.entries) { + if (!global.FormData || !global.FormData.prototype || !global.FormData.prototype.entries) { throw new Error(messages.MISSING_FORMDATA_ENTRIES_API); } } + + function checkTextEncoderApi() { + if (!global.TextEncoder || !global.TextEncoder.prototype) { + throw new Error(messages.MISSING_TEXT_ENCODER_API); + } + } }; diff --git a/www/helpers.js b/www/helpers.js index bdab928..6bb0886 100644 --- a/www/helpers.js +++ b/www/helpers.js @@ -18,7 +18,7 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64, checkTimeoutValue: checkTimeoutValue, checkUploadFileOptions: checkUploadFileOptions, getMergedHeaders: getMergedHeaders, - getProcessedData: getProcessedData, + processData: processData, handleMissingCallbacks: handleMissingCallbacks, handleMissingOptions: handleMissingOptions, injectCookieHandler: injectCookieHandler, @@ -374,7 +374,7 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64, return dataSerializer === 'multipart' ? 'FormData' : null; } - function getProcessedData(data, dataSerializer) { + function processData(data, dataSerializer, cb) { var currentDataType = jsUtil.getTypeOf(data); var allowedDataTypes = getAllowedDataTypes(dataSerializer); var allowedInstanceType = getAllowedInstanceType(dataSerializer); @@ -391,17 +391,67 @@ module.exports = function init(global, jsUtil, cookieHandler, messages, base64, throw new Error(messages.TYPE_MISMATCH_DATA + ' ' + allowedDataTypes.join(', ')); } - if (dataSerializer === 'utf8') { - data = { text: data }; + switch (dataSerializer) { + case 'utf8': + return cb({ text: data }); + case 'multipart': + return processFormData(data, cb); + default: + return cb(data); + } + } + + function processFormData(data, cb) { + dependencyValidator.checkBlobApi(); + dependencyValidator.checkFileReaderApi(); + dependencyValidator.checkFormDataApi(); + dependencyValidator.checkTextEncoderApi(); + + var textEncoder = new global.TextEncoder('utf8'); + var iterator = data.entries(); + + var result = { + buffers: [], + names: [], + fileNames: [], + types: [] + }; + + processFormDataIterator(iterator, textEncoder, result, cb); + } + + function processFormDataIterator(iterator, textEncoder, result, onFinished) { + var entry = iterator.next(); + + if (entry.done) { + return onFinished(result); } - if (dataSerializer === 'multipart') { - dependencyValidator.checkFormDataApi(); + if (entry.value[1] instanceof global.Blob) { + var reader = new global.FileReader(); - // TODO + reader.onload = function() { + result.buffers.push(base64.fromArrayBuffer(reader.result)); + result.names.push(entry.value[0]); + result.fileNames.push(entry.value[1].name || 'blob'); + result.types.push(entry.value[1].type || ''); + processFormDataIterator(iterator, textEncoder, result, onFinished); + }; + + return reader.readAsArrayBuffer(entry.value[1]); } - return data; + if (jsUtil.getTypeOf(entry.value[1]) === 'String') { + result.buffers.push(base64.fromArrayBuffer(textEncoder.encode(entry.value[1]).buffer)); + result.names.push(entry.value[0]); + result.fileNames.push(null); + result.types.push('text/plain'); + + return processFormDataIterator(iterator, textEncoder, result, onFinished) + } + + // skip items which are not supported + processFormDataIterator(iterator, textEncoder, result, onFinished); } function handleMissingCallbacks(successFn, failFn) { diff --git a/www/messages.js b/www/messages.js index 1fec793..03e02dc 100644 --- a/www/messages.js +++ b/www/messages.js @@ -19,8 +19,11 @@ module.exports = { INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value, ', MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function', MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function', - MISSING_FORMDATA_API: 'advanced-http: FormData API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/FormData-API-requirements for more info.', - MISSING_FORMDATA_ENTRIES_API: 'advanced-http: This webview does not implement FormData API specification correctly, FormData.entries() is missing. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/FormData-API-requirements for more info.', + MISSING_BLOB_API: 'advanced-http: Blob API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/Web-APIs-required-for-Multipart-requests for more info.', + MISSING_FILE_READER_API: 'advanced-http: FileReader API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/Web-APIs-required-for-Multipart-requests for more info.', + MISSING_FORMDATA_API: 'advanced-http: FormData API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/Web-APIs-required-for-Multipart-requests for more info.', + MISSING_FORMDATA_ENTRIES_API: 'advanced-http: This webview does not implement FormData API specification correctly, FormData.entries() is missing. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/Web-APIs-required-for-Multipart-requests for more info.', + MISSING_TEXT_ENCODER_API: 'advanced-http: TextEncoder API is not supported in this webview. If you want to use "multipart/form-data" requests, you need to load a polyfill library before loading this plugin. Check out https://github.com/silkimen/cordova-plugin-advanced-http/wiki/Web-APIs-required-for-Multipart-requests for more info.', POST_PROCESSING_FAILED: 'advanced-http: an error occured during post processing response:', TYPE_MISMATCH_DATA: 'advanced-http: "data" option is configured to support only following data types:', TYPE_MISMATCH_FILE_PATHS: 'advanced-http: "filePaths" option needs to be an string array, ', diff --git a/www/public-interface.js b/www/public-interface.js index 1018504..10d81f6 100644 --- a/www/public-interface.js +++ b/www/public-interface.js @@ -152,8 +152,9 @@ module.exports = function init(exec, cookieHandler, urlUtil, helpers, globalConf case 'post': case 'put': case 'patch': - var data = helpers.getProcessedData(options.data, options.serializer); - return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]); + return helpers.processData(options.data, options.serializer, function(data) { + exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [url, data, options.serializer, headers, options.timeout, options.followRedirect, options.responseType]); + }); case 'upload': var fileOptions = helpers.checkUploadFileOptions(options.filePath, options.name); return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFiles', [url, headers, fileOptions.filePaths, fileOptions.names, options.timeout, options.followRedirect, options.responseType]);