123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- module.exports = function init(global, jsUtil, cookieHandler, messages, base64, errorCodes, dependencyValidator, ponyfills) {
- var validSerializers = ['urlencoded', 'json', 'utf8', 'raw', 'multipart'];
- var validCertModes = ['default', 'nocheck', 'pinned', 'legacy'];
- var validClientAuthModes = ['none', 'systemstore', 'buffer'];
- var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'options', 'upload', 'download'];
- var validResponseTypes = ['text', 'json', 'arraybuffer', 'blob'];
-
- var interface = {
- b64EncodeUnicode: b64EncodeUnicode,
- checkClientAuthMode: checkClientAuthMode,
- checkClientAuthOptions: checkClientAuthOptions,
- checkDownloadFilePath: checkDownloadFilePath,
- checkFollowRedirectValue: checkFollowRedirectValue,
- checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
- checkForInvalidHeaderValue: checkForInvalidHeaderValue,
- checkSerializer: checkSerializer,
- checkSSLCertMode: checkSSLCertMode,
- checkTimeoutValue: checkTimeoutValue,
- checkUploadFileOptions: checkUploadFileOptions,
- getMergedHeaders: getMergedHeaders,
- processData: processData,
- handleMissingCallbacks: handleMissingCallbacks,
- handleMissingOptions: handleMissingOptions,
- injectCookieHandler: injectCookieHandler,
- injectFileEntryHandler: injectFileEntryHandler,
- injectRawResponseHandler: injectRawResponseHandler,
- };
-
- // expose all functions for testing purposes
- if (init.debug) {
- interface.mergeHeaders = mergeHeaders;
- interface.checkForValidStringValue = checkForValidStringValue;
- interface.checkKeyValuePairObject = checkKeyValuePairObject;
- interface.checkHttpMethod = checkHttpMethod;
- interface.checkResponseType = checkResponseType;
- interface.checkHeadersObject = checkHeadersObject;
- interface.checkParamsObject = checkParamsObject;
- interface.resolveCookieString = resolveCookieString;
- interface.createFileEntry = createFileEntry;
- interface.getCookieHeader = getCookieHeader;
- interface.getMatchingHostHeaders = getMatchingHostHeaders;
- interface.getAllowedDataTypes = getAllowedDataTypes;
- }
-
- return interface;
-
- // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
- function b64EncodeUnicode(str) {
- return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
- return String.fromCharCode('0x' + p1);
- }));
- }
-
- function mergeHeaders(globalHeaders, localHeaders) {
- var globalKeys = Object.keys(globalHeaders);
- var key;
-
- for (var i = 0; i < globalKeys.length; i++) {
- key = globalKeys[i];
-
- if (!localHeaders.hasOwnProperty(key)) {
- localHeaders[key] = globalHeaders[key];
- }
- }
-
- return localHeaders;
- }
-
- function checkForValidStringValue(list, value, onInvalidValueMessage) {
- if (jsUtil.getTypeOf(value) !== 'String') {
- throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
- }
-
- value = value.trim().toLowerCase();
-
- if (list.indexOf(value) === -1) {
- throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
- }
-
- return value;
- }
-
- function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
- if (jsUtil.getTypeOf(obj) !== 'Object') {
- throw new Error(onInvalidValueMessage);
- }
-
- var keys = Object.keys(obj);
-
- for (var i = 0; i < keys.length; i++) {
- if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) {
- throw new Error(onInvalidValueMessage);
- }
- }
-
- return obj;
- }
-
- function checkArray(array, allowedDataTypes, onInvalidValueMessage) {
- if (jsUtil.getTypeOf(array) !== 'Array') {
- throw new Error(onInvalidValueMessage);
- }
-
- for (var i = 0; i < array.length; ++i) {
- if (allowedDataTypes.indexOf(jsUtil.getTypeOf(array[i])) === -1) {
- throw new Error(onInvalidValueMessage);
- }
- }
-
- return array;
- }
-
- function checkHttpMethod(method) {
- return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD);
- }
-
- function checkResponseType(type) {
- return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE);
- }
-
- function checkSerializer(serializer) {
- return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
- }
-
- function checkSSLCertMode(mode) {
- return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE);
- }
-
- function checkClientAuthMode(mode) {
- return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE);
- }
-
- function checkClientAuthOptions(mode, options) {
- options = options || {};
-
- // none
- if (mode === validClientAuthModes[0]) {
- return {
- alias: null,
- rawPkcs: null,
- pkcsPassword: ''
- };
- }
-
- if (jsUtil.getTypeOf(options) !== 'Object') {
- throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS);
- }
-
- // systemstore
- if (mode === validClientAuthModes[1]) {
- if (jsUtil.getTypeOf(options.alias) !== 'String'
- && jsUtil.getTypeOf(options.alias) !== 'Undefined') {
- throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS);
- }
-
- return {
- alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias,
- rawPkcs: null,
- pkcsPassword: ''
- };
- }
-
- // buffer
- if (mode === validClientAuthModes[2]) {
- if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') {
- throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS);
- }
-
- if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') {
- throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD);
- }
-
- return {
- alias: null,
- rawPkcs: options.rawPkcs,
- pkcsPassword: options.pkcsPassword
- }
- }
- }
-
- function checkForBlacklistedHeaderKey(key) {
- if (key.toLowerCase() === 'cookie') {
- throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
- }
-
- return key;
- }
-
- function checkForInvalidHeaderValue(value) {
- var type = jsUtil.getTypeOf(value);
-
- if (type !== 'String' && type !== 'Null') {
- throw new Error(messages.INVALID_HEADER_VALUE);
- }
-
- return value;
- }
-
- function checkTimeoutValue(timeout) {
- if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) {
- throw new Error(messages.INVALID_TIMEOUT_VALUE);
- }
-
- return timeout;
- }
-
- function checkFollowRedirectValue(follow) {
- if (jsUtil.getTypeOf(follow) !== 'Boolean') {
- throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE);
- }
-
- return follow;
- }
-
- function checkHeadersObject(headers) {
- return checkKeyValuePairObject(headers, ['String'], messages.TYPE_MISMATCH_HEADERS);
- }
-
- function checkParamsObject(params) {
- return checkKeyValuePairObject(params, ['String', 'Array'], messages.TYPE_MISMATCH_PARAMS);
- }
-
- function checkDownloadFilePath(filePath) {
- if (!filePath || jsUtil.getTypeOf(filePath) !== 'String') {
- throw new Error(messages.INVALID_DOWNLOAD_FILE_PATH);
- }
-
- return filePath;
- }
-
- function checkUploadFileOptions(filePaths, names) {
- if (jsUtil.getTypeOf(filePaths) === 'String') {
- filePaths = [filePaths];
- }
-
- if (jsUtil.getTypeOf(names) === 'String') {
- names = [names];
- }
-
- var opts = {
- filePaths: checkArray(filePaths, ['String'], messages.TYPE_MISMATCH_FILE_PATHS),
- names: checkArray(names, ['String'], messages.TYPE_MISMATCH_NAMES)
- };
-
- if (!opts.filePaths.length) {
- throw new Error(messages.EMPTY_FILE_PATHS);
- }
-
- if (!opts.names.length) {
- throw new Error(messages.EMPTY_NAMES);
- }
-
- return opts;
- }
-
- function resolveCookieString(headers) {
- var keys = Object.keys(headers || {});
-
- for (var i = 0; i < keys.length; ++i) {
- if (keys[i].match(/^set-cookie$/i)) {
- return headers[keys[i]];
- }
- }
-
- return null;
- }
-
- function createFileEntry(rawEntry) {
- var entry = new (require('cordova-plugin-file.FileEntry'))();
-
- entry.isDirectory = rawEntry.isDirectory;
- entry.isFile = rawEntry.isFile;
- entry.name = rawEntry.name;
- entry.fullPath = rawEntry.fullPath;
- entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == global.PERSISTENT ? 'persistent' : 'temporary'));
- entry.nativeURL = rawEntry.nativeURL;
-
- return entry;
- }
-
- function injectCookieHandler(url, cb) {
- return function (response) {
- cookieHandler.setCookieFromString(url, resolveCookieString(response.headers));
- cb(response);
- }
- }
-
- function injectRawResponseHandler(responseType, success, failure) {
- return function (response) {
- var dataType = jsUtil.getTypeOf(response.data);
-
- // don't need post-processing if it's already binary type (on browser platform)
- if (dataType === 'ArrayBuffer' || dataType === 'Blob') {
- return success(response);
- }
-
- try {
- // json
- if (responseType === validResponseTypes[1]) {
- response.data = response.data === ''
- ? undefined
- : JSON.parse(response.data);
- }
-
- // arraybuffer
- else if (responseType === validResponseTypes[2]) {
- response.data = response.data === ''
- ? null
- : base64.toArrayBuffer(response.data);
- }
-
- // blob
- else if (responseType === validResponseTypes[3]) {
- if (response.data === '') {
- response.data = null;
- } else {
- var buffer = base64.toArrayBuffer(response.data);
- var type = response.headers['content-type'] || '';
- var blob = new Blob([buffer], { type: type });
- response.data = blob;
- }
- }
-
- success(response);
- } catch (error) {
- failure({
- status: errorCodes.POST_PROCESSING_FAILED,
- error: messages.POST_PROCESSING_FAILED + ' ' + error.message,
- url: response.url,
- headers: response.headers
- });
- }
- }
- }
-
- function injectFileEntryHandler(cb) {
- return function (response) {
- cb(createFileEntry(response.file));
- }
- }
-
- function getCookieHeader(url) {
- var cookieString = cookieHandler.getCookieString(url);
-
- if (cookieString.length) {
- return { Cookie: cookieHandler.getCookieString(url) };
- }
-
- return {};
- }
-
- function getMatchingHostHeaders(url, headersList) {
- var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i);
- var domain = matches && matches[1];
-
- return headersList[domain] || null;
- }
-
- function getMergedHeaders(url, requestHeaders, predefinedHeaders) {
- var globalHeaders = predefinedHeaders['*'] || {};
- var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {};
- var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders);
-
- mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders);
- mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url));
-
- return mergedHeaders;
- }
-
- function getAllowedDataTypes(dataSerializer) {
- switch (dataSerializer) {
- case 'utf8':
- return ['String'];
- case 'urlencoded':
- return ['Object'];
- case 'json':
- return ['Array', 'Object'];
- case 'raw':
- return ['Uint8Array', 'ArrayBuffer'];
- default:
- return [];
- }
- }
-
- function getAllowedInstanceTypes(dataSerializer) {
- return dataSerializer === 'multipart' ? ['FormData'] : null;
- }
-
- function processData(data, dataSerializer, cb) {
- var currentDataType = jsUtil.getTypeOf(data);
- var allowedDataTypes = getAllowedDataTypes(dataSerializer);
- var allowedInstanceTypes = getAllowedInstanceTypes(dataSerializer);
-
- if (allowedInstanceTypes) {
- var isCorrectInstanceType = false;
-
- allowedInstanceTypes.forEach(function (type) {
- if ((global[type] && data instanceof global[type]) || (ponyfills[type] && data instanceof ponyfills[type])) {
- isCorrectInstanceType = true;
- }
- });
-
- if (!isCorrectInstanceType) {
- throw new Error(messages.INSTANCE_TYPE_MISMATCH_DATA + ' ' + allowedInstanceTypes.join(', '));
- }
- }
-
- if (!allowedInstanceTypes && allowedDataTypes.indexOf(currentDataType) === -1) {
- throw new Error(messages.TYPE_MISMATCH_DATA + ' ' + allowedDataTypes.join(', '));
- }
-
- switch (dataSerializer) {
- case 'utf8':
- return cb({ text: data });
- case 'raw':
- return cb(currentDataType === 'Uint8Array' ? data.buffer : data);
- case 'multipart':
- return processFormData(data, cb);
- default:
- return cb(data);
- }
- }
-
- function processFormData(data, cb) {
- dependencyValidator.checkBlobApi();
- dependencyValidator.checkFileReaderApi();
- dependencyValidator.checkTextEncoderApi();
- dependencyValidator.checkFormDataInstance(data);
-
- 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 (entry.value[1] instanceof global.Blob || entry.value[1] instanceof global.File) {
- var reader = new global.FileReader();
-
- reader.onload = function () {
- result.buffers.push(base64.fromArrayBuffer(reader.result));
- result.names.push(entry.value[0]);
- result.fileNames.push(entry.value[1].name !== undefined ? entry.value[1].name : 'blob');
- result.types.push(entry.value[1].type || '');
- processFormDataIterator(iterator, textEncoder, result, onFinished);
- };
-
- return reader.readAsArrayBuffer(entry.value[1]);
- }
-
- 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) {
- if (jsUtil.getTypeOf(successFn) !== 'Function') {
- throw new Error(messages.MANDATORY_SUCCESS);
- }
-
- if (jsUtil.getTypeOf(failFn) !== 'Function') {
- throw new Error(messages.MANDATORY_FAIL);
- }
- }
-
- function handleMissingOptions(options, globals) {
- options = options || {};
-
- return {
- data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data,
- filePath: options.filePath,
- followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect),
- headers: checkHeadersObject(options.headers || {}),
- method: checkHttpMethod(options.method || validHttpMethods[0]),
- name: options.name,
- params: checkParamsObject(options.params || {}),
- responseType: checkResponseType(options.responseType || validResponseTypes[0]),
- serializer: checkSerializer(options.serializer || globals.serializer),
- timeout: checkTimeoutValue(options.timeout || globals.timeout),
- };
- }
- };
|