MOBILE-2349 ws: Fix expected type of WS post calls

main
Pau Ferrer Ocaña 2018-03-14 11:28:51 +01:00
parent 3b8b44c23a
commit d02b97b913
6 changed files with 88 additions and 74 deletions

View File

@ -153,9 +153,9 @@ export class AddonModBookProvider {
return promise.then((url) => {
// Fetch the URL content.
const observable = this.http.get(url);
const promise = this.http.get(url).toPromise();
return this.utils.observableToPromise(observable).then((response: Response): any => {
return promise.then((response: Response): any => {
const content = response.text();
if (typeof content !== 'string') {
return Promise.reject(null);

View File

@ -689,13 +689,13 @@ export class CoreSite {
* @return {Promise<any>} Promise resolved with the WS response.
*/
protected getFromCache(method: string, data: any, preSets: CoreSiteWSPreSets, emergency?: boolean): Promise<any> {
const id = this.getCacheId(method, data);
let promise;
if (!this.db || !preSets.getFromCache) {
return Promise.reject(null);
}
const id = this.getCacheId(method, data);
let promise;
if (preSets.getCacheUsingCacheKey || (emergency && preSets.getEmergencyCacheUsingCacheKey)) {
promise = this.db.getRecords(this.WS_CACHE_TABLE, { key: preSets.cacheKey }).then((entries) => {
if (!entries.length) {
@ -751,36 +751,37 @@ export class CoreSite {
* @return {Promise<any>} Promise resolved when the response is saved.
*/
protected saveToCache(method: string, data: any, response: any, preSets: CoreSiteWSPreSets): Promise<any> {
const id = this.getCacheId(method, data),
entry: any = {
id: id,
data: JSON.stringify(response)
};
let cacheExpirationTime = CoreConfigConstants.cache_expiration_time,
promise;
if (!this.db) {
return Promise.reject(null);
}
let promise;
if (preSets.uniqueCacheKey) {
// Cache key must be unique, delete all entries with same cache key.
promise = this.deleteFromCache(method, data, preSets, true).catch(() => {
// Ignore errors.
});
} else {
if (preSets.uniqueCacheKey) {
// Cache key must be unique, delete all entries with same cache key.
promise = this.deleteFromCache(method, data, preSets, true).catch(() => {
// Ignore errors.
});
} else {
promise = Promise.resolve();
promise = Promise.resolve();
}
return promise.then(() => {
const id = this.getCacheId(method, data),
entry: any = {
id: id,
data: JSON.stringify(response)
};
let cacheExpirationTime = CoreConfigConstants.cache_expiration_time;
cacheExpirationTime = isNaN(cacheExpirationTime) ? 300000 : cacheExpirationTime;
entry.expirationTime = new Date().getTime() + cacheExpirationTime;
if (preSets.cacheKey) {
entry.key = preSets.cacheKey;
}
return promise.then(() => {
cacheExpirationTime = isNaN(cacheExpirationTime) ? 300000 : cacheExpirationTime;
entry.expirationTime = new Date().getTime() + cacheExpirationTime;
if (preSets.cacheKey) {
entry.key = preSets.cacheKey;
}
return this.db.insertOrUpdateRecord(this.WS_CACHE_TABLE, entry, { id: id });
});
}
return this.db.insertOrUpdateRecord(this.WS_CACHE_TABLE, entry, { id: id });
});
}
/**
@ -793,17 +794,17 @@ export class CoreSite {
* @return {Promise<any>} Promise resolved when the entries are deleted.
*/
protected deleteFromCache(method: string, data: any, preSets: CoreSiteWSPreSets, allCacheKey?: boolean): Promise<any> {
const id = this.getCacheId(method, data);
if (!this.db) {
return Promise.reject(null);
} else {
if (allCacheKey) {
return this.db.deleteRecords(this.WS_CACHE_TABLE, { key: preSets.cacheKey });
} else {
return this.db.deleteRecords(this.WS_CACHE_TABLE, { id: id });
}
}
const id = this.getCacheId(method, data);
if (allCacheKey) {
return this.db.deleteRecords(this.WS_CACHE_TABLE, { key: preSets.cacheKey });
}
return this.db.deleteRecords(this.WS_CACHE_TABLE, { id: id });
}
/*
@ -985,9 +986,9 @@ export class CoreSite {
return Promise.resolve({ code: 0 });
}
const observable = this.http.post(checkUrl, { service: service }).timeout(CoreConstants.WS_TIMEOUT);
const promise = this.http.post(checkUrl, { service: service }).timeout(CoreConstants.WS_TIMEOUT).toPromise();
return this.utils.observableToPromise(observable).then((data: any) => {
return promise.then((data: any) => {
if (typeof data != 'undefined' && data.errorcode === 'requirecorrectaccess') {
if (!retrying) {
this.siteUrl = this.urlUtils.addOrRemoveWWW(this.siteUrl);

View File

@ -161,7 +161,7 @@ export class CoreLangProvider {
return language;
}).catch(() => {
// User hasn't defined a language. If default language is forced, use it.
if (CoreConfigConstants.forcedefaultlanguage && !CoreConfigConstants.forcedefaultlanguage) {
if (!CoreConfigConstants.forcedefaultlanguage) {
return CoreConfigConstants.default_lang;
}

View File

@ -387,9 +387,9 @@ export class CoreSitesProvider {
data.service = 'c';
}
const observable = this.http.post(siteUrl + '/login/token.php', data).timeout(CoreConstants.WS_TIMEOUT);
const promise = this.http.post(siteUrl + '/login/token.php', data).timeout(CoreConstants.WS_TIMEOUT).toPromise();
return this.utils.observableToPromise(observable).catch((error) => {
return promise.catch((error) => {
return Promise.reject(error.message);
}).then((data: any) => {
if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) {
@ -426,9 +426,9 @@ export class CoreSitesProvider {
password: password,
service: service
},
observable = this.http.post(siteUrl + '/login/token.php', params).timeout(CoreConstants.WS_TIMEOUT);
promise = this.http.post(siteUrl + '/login/token.php', params).timeout(CoreConstants.WS_TIMEOUT).toPromise();
return this.utils.observableToPromise(observable).then((data: any): any => {
return promise.then((data: any): any => {
if (typeof data == 'undefined') {
return Promise.reject(this.translate.instant('core.cannotconnect'));
} else {

View File

@ -850,26 +850,6 @@ export class CoreUtilsProvider {
return mapped;
}
/**
* Given an observable, convert it to a Promise that will resolve with the first received value.
*
* @param {Observable<any>} obs The observable to convert.
* @return {Promise<any>} Promise.
*/
observableToPromise(obs: Observable<any>): Promise<any> {
return new Promise((resolve, reject): void => {
const subscription = obs.subscribe((data) => {
// Data received, unsubscribe.
subscription.unsubscribe();
resolve(data);
}, (error) => {
// Data received, unsubscribe.
subscription.unsubscribe();
reject(error);
});
});
}
/**
* Similar to AngularJS $q.defer().
*

View File

@ -238,9 +238,9 @@ export class CoreWSProvider {
siteUrl = preSets.siteUrl + '/lib/ajax/service.php';
const observable = this.http.post(siteUrl, JSON.stringify(ajaxData)).timeout(CoreConstants.WS_TIMEOUT);
const promise = this.http.post(siteUrl, JSON.stringify(ajaxData)).timeout(CoreConstants.WS_TIMEOUT).toPromise();
return this.utils.observableToPromise(observable).then((data: any) => {
return promise.then((data: any) => {
// Some moodle web services return null.
// If the responseExpected value is set then so long as no data is returned, we create a blank object.
if (!data && !preSets.responseExpected) {
@ -486,7 +486,7 @@ export class CoreWSProvider {
let promise = this.getPromiseHttp('head', url);
if (!promise) {
promise = this.utils.observableToPromise(this.commonHttp.head(url).timeout(CoreConstants.WS_TIMEOUT));
promise = this.commonHttp.head(url).timeout(CoreConstants.WS_TIMEOUT).toPromise();
promise = this.setPromiseHttp(promise, 'head', url);
}
@ -503,11 +503,18 @@ export class CoreWSProvider {
* @return {Promise<any>} Promise resolved with the response data in success and rejected with CoreWSError if it fails.
*/
performPost(method: string, siteUrl: string, ajaxData: any, preSets: CoreWSPreSets): Promise<any> {
// Perform the post request.
const observable = this.http.post(siteUrl, ajaxData).timeout(CoreConstants.WS_TIMEOUT);
let promise;
const options = {};
promise = this.utils.observableToPromise(observable).then((data: any) => {
// This is done because some returned values like 0 are treated as null if responseType is json.
if (preSets.typeExpected == 'number' || preSets.typeExpected == 'boolean' || preSets.typeExpected == 'string') {
// Avalaible values are: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseType
options['responseType'] = 'text';
}
// Perform the post request.
let promise = this.http.post(siteUrl, ajaxData, options).timeout(CoreConstants.WS_TIMEOUT).toPromise();
promise = promise.then((data: any) => {
// Some moodle web services return null.
// If the responseExpected value is set to false, we create a blank object if the response is null.
if (!data && !preSets.responseExpected) {
@ -517,9 +524,35 @@ export class CoreWSProvider {
if (!data) {
return Promise.reject(this.utils.createFakeWSError('core.serverconnection', true));
} else if (typeof data != preSets.typeExpected) {
this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`);
// If responseType is text an string will be returned, parse before returning.
if (typeof data == 'string') {
if (preSets.typeExpected == 'number') {
data = Number(data);
if (isNaN(data)) {
this.logger.warn(`Response expected type "${preSets.typeExpected}" cannot be parsed to number`);
return Promise.reject(this.utils.createFakeWSError('core.errorinvalidresponse', true));
return Promise.reject(this.utils.createFakeWSError('core.errorinvalidresponse', true));
}
} else if (preSets.typeExpected == 'boolean') {
if (data === 'true') {
data = true;
} else if (data === 'false') {
data = false;
} else {
this.logger.warn(`Response expected type "${preSets.typeExpected}" is not true or false`);
return Promise.reject(this.utils.createFakeWSError('core.errorinvalidresponse', true));
}
} else {
this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`);
return Promise.reject(this.utils.createFakeWSError('core.errorinvalidresponse', true));
}
} else {
this.logger.warn('Response of type "' + typeof data + `" received, expecting "${preSets.typeExpected}"`);
return Promise.reject(this.utils.createFakeWSError('core.errorinvalidresponse', true));
}
}
if (typeof data.exception !== 'undefined') {