- implement all HTTP operations as shorthand functions of "sendRequest"

- add some more type checking
This commit is contained in:
Sefa Ilkimen
2018-02-28 03:24:27 +01:00
parent 6b9ed72b9f
commit 63d859ad54
5 changed files with 153 additions and 285 deletions
+4 -4
View File
@@ -288,14 +288,14 @@ const tests = [
.should.be.equal('http://httpbin.org/get?myArray[]=val1&myArray[]=val2&myArray[]=val3&myString=testString');
}
},{
description: 'should reject non-string values in local header object #54',
expected: 'rejected: {"status": 0, "error": "advanced-http: header values must be strings" ...',
description: 'should throw on non-string values in local header object #54',
expected: 'throwed: {"message": "advanced-http: header values must be strings"}',
func: function(resolve, reject) {
cordova.plugin.http.get('http://httpbin.org/get', {}, { myTestHeader: 1 }, resolve, reject);
},
validationFunc: function(driver, result) {
result.type.should.be.equal('rejected');
result.data.error.should.be.equal('advanced-http: header values must be strings');
result.type.should.be.equal('throwed');
result.message.should.be.equal('advanced-http: header values must be strings');
}
},{
description: 'should throw an error while setting non-string value as global header #54',
-1
View File
@@ -27,7 +27,6 @@ describe('Advanced HTTP www interface', function() {
mock('cordova/exec', noop);
mock(`${PLUGIN_ID}.cookie-handler`, {});
mock(`${HELPERS_ID}.cookie-handler`, {});
mock(`${PLUGIN_ID}.messages`, require('../www/messages'));
mock(`${HELPERS_ID}.messages`, require('../www/messages'));
mock(`${PLUGIN_ID}.angular-integration`, { registerService: noop });
+111 -234
View File
@@ -1,30 +1,5 @@
/*global angular*/
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
* Modified by Andrew Stephan for Sync OnSet
* Modified by Sefa Ilkimen
*/
/*
* An HTTP Plugin for PhoneGap.
* A native HTTP Plugin for Cordova / PhoneGap.
*/
var pluginId = module.id.slice(0, module.id.lastIndexOf('.'));
@@ -33,222 +8,124 @@ var exec = require('cordova/exec');
var angularIntegration = require(pluginId +'.angular-integration');
var cookieHandler = require(pluginId + '.cookie-handler');
var helpers = require(pluginId + '.helpers');
var messages = require(pluginId + '.messages');
var internals = {
var globalConfigs = {
headers: {},
dataSerializer: 'urlencoded',
timeoutInSeconds: 60.0,
serializer: 'urlencoded',
timeout: 60.0,
};
var publicInterface = {
getBasicAuthHeader: function (username, password) {
return {'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password)};
},
useBasicAuth: function (username, password) {
this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
},
getHeaders: function (host) {
return internals.headers[host || '*'] || null;
},
setHeader: function () {
// this one is for being backward compatible
var host = '*';
var header = arguments[0];
var value = arguments[1];
getBasicAuthHeader: function (username, password) {
return {'Authorization': 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password)};
},
useBasicAuth: function (username, password) {
this.setHeader('*', 'Authorization', 'Basic ' + helpers.b64EncodeUnicode(username + ':' + password));
},
getHeaders: function (host) {
return globalConfigs.headers[host || '*'] || null;
},
setHeader: function () {
// this one is for being backward compatible
var host = '*';
var header = arguments[0];
var value = arguments[1];
if (arguments.length === 3) {
host = arguments[0];
header = arguments[1];
value = arguments[2];
}
if (header.toLowerCase() === 'cookie') {
throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
}
if (helpers.getTypeOf(value) !== 'String') {
throw new Error(messages.HEADER_VALUE_MUST_BE_STRING);
}
internals.headers[host] = internals.headers[host] || {};
internals.headers[host][header] = value;
},
getDataSerializer: function () {
return internals.dataSerializer;
},
setDataSerializer: function (serializer) {
internals.dataSerializer = helpers.checkSerializer(serializer);
},
setCookie: function (url, cookie, options) {
cookieHandler.setCookie(url, cookie, options);
},
clearCookies: function () {
cookieHandler.clearCookies();
},
removeCookies: function (url, callback) {
cookieHandler.removeCookies(url, callback);
},
getCookieString: function (url) {
return cookieHandler.getCookieString(url);
},
getRequestTimeout: function () {
return internals.timeoutInSeconds;
},
setRequestTimeout: function (timeout) {
internals.timeoutInSeconds = timeout;
},
enableSSLPinning: function (enable, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'enableSSLPinning', [enable]);
},
acceptAllCerts: function (allow, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'acceptAllCerts', [allow]);
},
disableRedirect: function (disable, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'disableRedirect', [disable]);
},
validateDomainName: function (validate, success, failure) {
failure(messages.DEPRECATED_VDN);
},
sendRequest: function (url, options, success, failure) {
helpers.handleMissingCallbacks(success, failure);
options = helpers.handleMissingOptions(options, internals);
var headers = helpers.getMergedHeaders(url, options.headers, internals.headers);
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
var payload;
if ([ 'get', 'delete', 'head' ].indexOf(method) < 0) {
payload = helpers.getProcessedData(options.data, options.serializer);
} else {
payload = params;
}
return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [ url, payload, options.serializer, headers, options.timeout ]);
},
post: function (url, data, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
data = helpers.getProcessedData(data, internals.dataSerializer);
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'post', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
},
get: function (url, params, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
params = params || {};
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'get', [url, params, headers, internals.timeoutInSeconds]);
},
put: function (url, data, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
data = helpers.getProcessedData(data, internals.dataSerializer);
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'put', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
},
patch: function (url, data, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
data = helpers.getProcessedData(data, internals.dataSerializer);
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'patch', [url, data, internals.dataSerializer, headers, internals.timeoutInSeconds]);
},
delete: function (url, params, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
params = params || {};
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'delete', [url, params, headers, internals.timeoutInSeconds]);
},
head: function (url, params, headers, success, failure) {
helpers.handleMissingCallbacks(success, failure);
params = params || {};
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'head', [url, params, headers, internals.timeoutInSeconds]);
},
uploadFile: function (url, params, headers, filePath, name, success, failure) {
helpers.handleMissingCallbacks(success, failure);
params = params || {};
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [url, params, headers, filePath, name, internals.timeoutInSeconds]);
},
downloadFile: function (url, params, headers, filePath, success, failure) {
helpers.handleMissingCallbacks(success, failure);
params = params || {};
headers = helpers.getMergedHeaders(url, headers, internals.headers);
if (!helpers.checkHeaders(headers)) {
return helpers.onInvalidHeader(failure);
}
var onSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
var onFail = helpers.injectCookieHandler(url, failure);
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [url, params, headers, filePath, internals.timeoutInSeconds]);
if (arguments.length === 3) {
host = arguments[0];
header = arguments[1];
value = arguments[2];
}
helpers.checkForBlacklistedHeaderKey(header);
helpers.checkForInvalidHeaderValue(value);
globalConfigs.headers[host] = globalConfigs.headers[host] || {};
globalConfigs.headers[host][header] = value;
},
getDataSerializer: function () {
return globalConfigs.serializer;
},
setDataSerializer: function (serializer) {
globalConfigs.serializer = helpers.checkSerializer(serializer);
},
setCookie: function (url, cookie, options) {
cookieHandler.setCookie(url, cookie, options);
},
clearCookies: function () {
cookieHandler.clearCookies();
},
removeCookies: function (url, callback) {
cookieHandler.removeCookies(url, callback);
},
getCookieString: function (url) {
return cookieHandler.getCookieString(url);
},
getRequestTimeout: function () {
return globalConfigs.timeout;
},
setRequestTimeout: function (timeout) {
globalConfigs.timeout = timeout;
},
enableSSLPinning: function (enable, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'enableSSLPinning', [enable]);
},
acceptAllCerts: function (allow, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'acceptAllCerts', [allow]);
},
disableRedirect: function (disable, success, failure) {
return exec(success, failure, 'CordovaHttpPlugin', 'disableRedirect', [disable]);
},
sendRequest: function (url, options, success, failure) {
helpers.handleMissingCallbacks(success, failure);
options = helpers.handleMissingOptions(options, globalConfigs);
var headers = helpers.getMergedHeaders(url, options.headers, globalConfigs.headers);
var onSuccess = helpers.injectCookieHandler(url, success);
var onFail = helpers.injectCookieHandler(url, failure);
switch(options.method) {
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 ]);
case 'upload':
return exec(onSuccess, onFail, 'CordovaHttpPlugin', 'uploadFile', [ url, options.params, headers, options.filePath, options.name, options.timeout ]);
case 'download':
var onDownloadSuccess = helpers.injectCookieHandler(url, helpers.injectFileEntryHandler(success));
return exec(onDownloadSuccess, onFail, 'CordovaHttpPlugin', 'downloadFile', [ url, options.params, headers, options.filePath, options.timeout ]);
default:
return exec(onSuccess, onFail, 'CordovaHttpPlugin', options.method, [ url, options.params, headers, options.timeout ]);
}
},
post: function (url, data, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'post', data: data, headers: headers }, success, failure);
},
get: function (url, params, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'get', params: params, headers: headers }, success, failure);
},
put: function (url, data, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'put', data: data, headers: headers }, success, failure);
},
patch: function (url, data, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'patch', data: data, headers: headers }, success, failure);
},
delete: function (url, params, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'delete', params: params, headers: headers }, success, failure);
},
head: function (url, params, headers, success, failure) {
return publicInterface.sendRequest(url, { method: 'head', params: params, headers: headers }, success, failure);
},
uploadFile: function (url, params, headers, filePath, name, success, failure) {
return publicInterface.sendRequest(url, { method: 'upload', params: params, headers: headers, filePath: filePath, name: name }, success, failure);
},
downloadFile: function (url, params, headers, filePath, success, failure) {
return publicInterface.sendRequest(url, { method: 'download', params: params, headers: headers, filePath: filePath }, success, failure);
}
};
// angular service is deprecated and will be removed anytime soon
angularIntegration.registerService(publicInterface);
module.exports = publicInterface;
+36 -42
View File
@@ -3,19 +3,20 @@ var cookieHandler = require(pluginId + '.cookie-handler');
var messages = require(pluginId + '.messages');
var validSerializers = [ 'urlencoded', 'json', 'utf8' ];
var validHttpMethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete'];
var validHttpMethods = [ 'get', 'put', 'post', 'patch', 'head', 'delete', 'upload', 'download' ];
module.exports = {
b64EncodeUnicode: b64EncodeUnicode,
getTypeOf: getTypeOf,
checkHeaders: checkHeaders,
onInvalidHeader: onInvalidHeader,
checkSerializer: checkSerializer,
checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey,
checkForInvalidHeaderValue: checkForInvalidHeaderValue,
injectCookieHandler: injectCookieHandler,
injectFileEntryHandler: injectFileEntryHandler,
getMergedHeaders: getMergedHeaders,
getProcessedData: getProcessedData,
handleMissingCallbacks: handleMissingCallbacks
handleMissingCallbacks: handleMissingCallbacks,
handleMissingOptions: handleMissingOptions
};
// Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22
@@ -40,29 +41,6 @@ function mergeHeaders(globalHeaders, localHeaders) {
return localHeaders;
}
function checkHeaders(headers) {
var keys = Object.keys(headers);
var key;
for (var i = 0; i < keys.length; i++) {
key = keys[i];
if (getTypeOf(headers[key]) !== 'String') {
return false;
}
}
return true;
}
function onInvalidHeader(handler) {
handler({
status: 0,
error: messages.HEADER_VALUE_MUST_BE_STRING,
headers: {}
});
}
function checkForValidStringValue(list, value, onInvalidValueMessage) {
if (getTypeOf(value) !== 'String') {
throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
@@ -70,14 +48,14 @@ function checkForValidStringValue(list, value, onInvalidValueMessage) {
value = value.trim().toLowerCase();
if (list.indexOf(value) > -1) {
return value;
if (list.indexOf(value) === -1) {
throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
}
throw new Error(onInvalidValueMessage + ' ' + list.join(', '));
return value;
}
function checkKeyValuePairObject(obj, onInvalidValueMessage) {
function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) {
if (getTypeOf(obj) !== 'Object') {
throw new Error(onInvalidValueMessage);
}
@@ -85,9 +63,7 @@ function checkKeyValuePairObject(obj, onInvalidValueMessage) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (getTypeOf(obj[key]) !== 'String') {
if (allowedChildren.indexOf(getTypeOf(obj[keys[i]])) === -1) {
throw new Error(onInvalidValueMessage);
}
}
@@ -103,6 +79,22 @@ function checkSerializer(serializer) {
return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER);
}
function checkForBlacklistedHeaderKey(key) {
if (key.toLowerCase() === 'cookie') {
throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED);
}
return key;
}
function checkForInvalidHeaderValue(value) {
if (getTypeOf(value) !== 'String') {
throw new Error(messages.INVALID_HEADERS_VALUE);
}
return value;
}
function checkTimeoutValue(timeout) {
if (getTypeOf(timeout) !== 'Number' || timeout < 0) {
throw new Error(messages.INVALID_TIMEOUT_VALUE);
@@ -112,11 +104,11 @@ function checkTimeoutValue(timeout) {
}
function checkHeadersObject(headers) {
checkKeyValuePairObject(headers, messages.INVALID_HEADERS_VALUE);
return checkKeyValuePairObject(headers, [ 'String' ], messages.INVALID_HEADERS_VALUE);
}
function checkParamsObject(params) {
checkKeyValuePairObject(params, messages.INVALID_PARAMS_VALUE);
return checkKeyValuePairObject(params, [ 'String', 'Array' ], messages.INVALID_PARAMS_VALUE);
}
function resolveCookieString(headers) {
@@ -245,11 +237,13 @@ function handleMissingOptions(options, globals) {
options = options || {};
return {
method: checkHttpMethod(options.method || validHttpMethods[0]);
serializer: checkSerializer(options.serializer || globals.dataSerializer);
timeout: checkTimeoutValue(options.timeout || globals.timeoutInSeconds);
headers: checkHeadersObject(options.headers || {});
params: checkParamsObject(options.params || {});
data: options.data || null;
method: checkHttpMethod(options.method || validHttpMethods[0]),
serializer: checkSerializer(options.serializer || globals.serializer),
timeout: checkTimeoutValue(options.timeout || globals.timeout),
headers: checkHeadersObject(options.headers || {}),
params: checkParamsObject(options.params || {}),
data: options.data || null,
filePath: options.filePath || '',
name: options.name || ''
};
}
+2 -4
View File
@@ -1,13 +1,11 @@
module.exports = {
ADDING_COOKIES_NOT_SUPPORTED: 'advanced-http: "setHeader" does not support adding cookies, please use "setCookie" function instead',
DATA_TYPE_MISMATCH: 'advanced-http: "data" argument supports only following data types:',
DEPRECATED_VDN: 'advanced-http: "validateDomainName" is no more supported, please see change log for further info',
HEADER_VALUE_MUST_BE_STRING: 'advanced-http: header values must be strings',
MANDATORY_SUCCESS: 'advanced-http: missing mandatory "onSuccess" callback function',
MANDATORY_FAIL: 'advanced-http: missing mandatory "onFail" callback function',
INVALID_HTTP_METHOD: 'advanced-http: invalid HTTP method, supported methods are:',
INVALID_DATA_SERIALIZER: 'advanced-http: invalid serializer, supported serializers are:',
INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive float value',
INVALID_HEADERS_VALUE: 'advanced-http: invalid headers object, needs to be an object with strings',
INVALID_HEADERS_VALUE: 'advanced-http: header values must be strings',
INVALID_TIMEOUT_VALUE: 'advanced-http: invalid timeout value, needs to be a positive numeric value',
INVALID_PARAMS_VALUE: 'advanced-http: invalid params object, needs to be an object with strings'
};